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?

lte__
  • 7,175
  • 25
  • 74
  • 131

2 Answers2

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.

artm
  • 17,291
  • 6
  • 38
  • 54
  • How do I make sure the buffer is null terminated? – lte__ Nov 04 '16 at 11:04
  • Just initialise it `char name[25] = "";` – artm Nov 04 '16 at 11:05
  • If you need to use `name` in a loop, then `memset` it to all zero at the beginning of the loop – artm Nov 04 '16 at 11:07
  • *I'm not sure the reason you want to use low level system calls `open`, `lseek`, `write`.* Performance? Control? Flexibility? Reduced dependencies? Learning? – Andrew Henle Nov 04 '16 at 11:09
  • @artm Try doing lock-free atomic reads/writes from random file offsets with `fread()`/`fwrite()` – Andrew Henle Nov 04 '16 at 11:44
  • @AndrewHenle I agree, some low level operations as you mentioned would require I/O system calls. I think for common user space problems like OP we don't really need that – artm Nov 04 '16 at 11:52
  • http://stackoverflow.com/questions/544662/is-there-any-ordinary-reason-to-use-open-instead-of-fopen – artm Nov 04 '16 at 11:54
  • @artm initialising it `char name[25] = ""` didn't do anything. – lte__ Nov 04 '16 at 11:55
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.

DUman
  • 2,560
  • 13
  • 16