1

This code, for some reason, is giving me a corrupt final character- both writing to file and printf do not have the last character entered

#include <stdio.h>
#include <stdlib.h>
#include "ssem.h"

int main(){
    int sem_WF, sem_WF_key = 123456, fileID, callStatus;
    char user_input[21];
    
    /*sem_WF = sem_open(sem_WF_key);*/

    fileID = creat ("data", 384);
    if (fileID<0) {printf("Error with creat"); return 0;}

    printf("Enter up to 20 characters: ");
    
    fgets(user_input, 20, stdin);
    printf("%s\n", user_input);

    callStatus = write(fileID, user_input, 20);
    if (callStatus<0) {printf("error with write"); return 0;}

    callStatus = close(fileID);
    if (callStatus<0) {printf("error with close"); return 0;}

    return 0;
}
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
man_idk
  • 55
  • 5
  • 2
    `fgets(user_input, 20, stdin);` will write at most 19 characters other than `'\0'` (at most 20 in total) in `user_input`, which, BTW, you correctly defined as capable of holding 21 characters. I'm lazy ... I usually do `fgets(foo, sizeof foo, stdin)` – pmg Oct 12 '20 at 07:44
  • @pmg, if I may interject, I don't think you're lazy at all, writing `sizeof foo` is actually more laborious that writing just `20` ;) – anastaciu Oct 12 '20 at 11:33
  • 1
    @anastaciu, well, lazy in the context of sometimes I use `100`, or `1000`, or `500`, or `20`, or `256`, ... (depends on I don't know what) and it's more trouble checking what I used than typing `sizeof buf` (also usually these kind of array is called `buf`) :) – pmg Oct 12 '20 at 11:53
  • @pmg, I see, that's laziness of the best kind – anastaciu Oct 12 '20 at 13:54

1 Answers1

2

In write you have a problem, you need to pass the length of the string in the count argument, i.e. strlen(user_input) instead of 20:

write(fileID, user_input, strlen(user_input));

Otherwise it will write all 20 characters regardless of the size of the string stored in user_input. e.g if the string has 8 characters it will write those 8 characters plus the null terminator plus whatever garbage values are stored in the remaining elements of the char array until the size of 20.

Also to note that the actual length of the string is never 20 because of the way you use fgets, it will have at most 19 characters + the null-byte(more details ahead), this null byte is also being written to the file.

Keep in mind that when you read the string from the file you'll need to null terminate it by hand, the above write will not store the null byte in the file.


Regarding fgets, it will store the null byte \0 in the last character of the destination buffer, so if you pass the size of 20, it will store at most 19 characters + the null byte. The good practice is to use the size of the destination buffer:

fgets(user_input, sizeof user_input, stdin);

Also to note is that fgets stores the \n newline character present in the input stream.

A string parsed with fgets will look like:

+---+---+---+---+---+---+----+----+
|'s'|'t'|'r'|'i'|'n'|'g'|'\n'|'\0'|
+---+---+---+---+---+---+----+----+

Unless \n is to be stored in the last element of the destination buffer in which case it will be left in the stdin buffer, and in its place will be a \0.

You can remove this \n character if you wish to do so with:

user_input[strcspn(user_input, "\n")] = '\0'; //#include <string.h>

Here is a Live Demo with the issues fixed.

anastaciu
  • 23,467
  • 7
  • 28
  • 53