C program doesn't see last letter at .txt file

Viewed 64

This code basically creates a txt file and add names and if users inputs new name it adds to txt file but it doesn't see the last letter like jack -> jac . Btw it saves names perfectly in txt file. So issue has to be at dosyaOku() .This informations must be enough but thanks to stackoverflow I need to add some more details.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


char allFile[1000][100],userName[100];
int i = 0;

int main()
{
    addSomeNames();
    dosyaOku();
    isimAl();
    isimKarsilastir();
    dosyaOku();
    return 0;
}
void isimKarsilastir()
{
    int a,ayni = 0;
    for (a=0 ; a < i; a++)
    {
        if (strcmp(allFile[a],userName) == 0)
        {
            printf("ayni\n");
            ayni++;
        }
        else
        {
            printf("farkli\n");
        }
    }
    if (ayni>0)
    {
        printf("Kullanici adi bulunmustur\n");
    }
    else
    {
        dosyaYaz();
    }
}
void dosyaYaz()
{
    FILE * ptrfile;
    ptrfile = fopen("sondokunus.txt","a");
    fprintf(ptrfile,"\n%s",userName);
    fclose(ptrfile);

}
void isimAl()
{

    printf("Isim giriniz: ");
    gets(userName);
    printf("Girdiginiz isim: %s",userName);


}
void dosyaOku()
{

    FILE *ptrfile = NULL;
    int *ptri;
    ptri = &i;
    *ptri = 0;
    int top = 0;

    ptrfile = fopen("sondokunus.txt", "r");
    while(fgets(allFile[*ptri], 100, ptrfile))
    {
        allFile[*ptri][strlen(allFile[*ptri]) - 1] = '\0';
        *ptri += 1;
    }
    top = *ptri;
    printf("\n Dosyadaki isimler: \n");
    for(*ptri = 0; *ptri < top; *ptri += 1)
    {
        printf("%s\n", allFile[*ptri]);
    }
    fclose(ptrfile);
}
void addSomeNames()
{
    FILE * ptrfile;
    ptrfile = fopen("sondokunus.txt", "w+");
    char names[100][100];
    strcpy(names[0],"mike");
    strcpy(names[1],"joe");
    strcpy(names[2],"jack");
    for (int n=0;n <= 2; n++)
    {
        fprintf(ptrfile,"\n%s", names[n]);
    }
    fclose(ptrfile);

}
3 Answers

Code has at least::

allFile[*ptri][strlen(allFile[*ptri]) - 1] = '\0'; as a problem.

When the string at allFile[*ptri] does not end with a "\n" (fairly common due to reading the last line in a text file), it lops off a non-'\n' character.

Instead

size_t length_of_string_without_linefeed = strcspn(allFile[*ptri], "\n");
allFile[*ptri][length_of_string_without_linefeed] = '\0';
// or
allFile[*ptri][strcspn(allFile[*ptri], "\n")] = '\0';

allFile[*ptri][strlen(allFile[*ptri]) - 1] is hacker exploitable.

If the first character in a line from the file is a null character, then code is like:

allFile[*ptri][(size_t)0 - 1]
// or 
allFile[*ptri][SIZE_MAX]

Which leads to undefined behavior.

Do not use - 1 with strlen(allFile[*ptri]) - 1 when strlen(allFile[*ptri]) == 0.

Further to chux's answer, I would use instead:

char *p = strchr( allFile[*ptri], '\n' );
if( p ) *p = '\0';

That makes abundantly clear what you're doing, and doesn't rely on overwriting the NUL terminator if the newline isn't present.

As noted in other answers, dosyaOku behaves incorrectly if it gets a line that doesn't end in \n, and you should fix that. But the reason your file looks like that in the first place is probably a separate bug in addSomeNames. You have

        fprintf(ptrfile,"\n%s", names[n]);

with the newline printed before the name. This means the file will begin with a blank line, and the last line will not have \n at the end. You probably wanted to write:

        fprintf(ptrfile,"%s\n", names[n]);
Related