0

I want to read some string input from the user and write it to a file. Right now I'm doing

char name[25];
scanf("%s", name);
int handle = open("./visitors.txt", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
if (handle < 0){
   printf("File error.\n");
   return;
}
lseek(handle, -sizeof(name), SEEK_END);
write(handle, name, sizeof(name));

This, of course is not right, since most of the time the user doesn't write 25 characters, only less, so when the user inputs 5 characters, the other 20 will be empty, and I end up having 5 chars the user put in and 20 chars gibberish in my output file. How can I make sure only the user input is being written to the file?

3
  • By reading the manual of scanf? %s causes the output to be null-terminated. Commented Nov 4, 2016 at 10:56
  • -sizeof(name) should be -(off_t)sizeof(name) Commented Nov 4, 2016 at 11:16
  • @M.M Doesn't make any difference. Commented Nov 4, 2016 at 11:57

2 Answers 2

1

You are using raw system calls to handle the file operations. Unless your intention is specifically to learn about system calls, you should not do that. The write call writes a number of bytes specified by the third parameter. sizeof(name) is wrong in this case. It will not return the length of the string, it will return the length of the entire buffer.

The standard strlen function gives you the string length. So running strlen(name) will give you 5 if the user enters 5 characters, unlike the sizeof you are using.

Unless you want to learn about system calls specifically, you should probably handle file operations with the C standard library, using fprintf to output to file, and functions such as fopen and fclose. Take a look at the fprintf docs that also link to the other functions.

Sign up to request clarification or add additional context in comments.

1 Comment

That was it! Using strlen() instead of sizeof() fixed it. Thank you!
1

I'm not sure the reason you want to use low level system calls open, lseek, write. Usually it's a lot more convenient to use standard C fopen, fscanf, fprintf functions for such tasks.

In this case, you may try fgets to get string input from stdin, then use fprintf with %s to write to file. You can still use buffer name[25] or name[100] (envision for largest input from stdin). Just initialise it properly to make sure it's NULL terminated. Then fprintf with %s would write the string properly (ie without gibberish ending) to file.

8 Comments

How do I make sure the buffer is null terminated?
Just initialise it char name[25] = "";
If you need to use name in a loop, then memset it to all zero at the beginning of the loop
I'm not sure the reason you want to use low level system calls open, lseek, write. Performance? Control? Flexibility? Reduced dependencies? Learning?
@artm Try doing lock-free atomic reads/writes from random file offsets with fread()/fwrite()
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.