Странные символы при получении str из файла в C - PullRequest
0 голосов
/ 08 мая 2018

Я попытался получить содержимое файла и поместить его в строку. Когда я запускаю свою программу и печатаю строку, впоследствии я получаю содержимое файла с некоторыми странными символами.

Мой код:

int size = 0;
char ch = 0;
char* content = 0;
FILE* fs = fopen(file, "r");
//getting file's content and put it into a string
while (ch != EOF)
{
    ch = (char)fgetc(fs);
    size++;
    content = myRealloc(content, size);
    content[size - 1] = ch;
} 
printf("%s", content);

myRealloc:

char* myRealloc(char* array, int size)
{
    char* temp = 0;
    temp = realloc(array, size * sizeof(char));
    return temp;
}

Содержимое файла:

1,2,3,4
5,6,7,8
a,b,c,d
e,f,g,h

Когда я печатаю:

1,2,3,4
5,6,7,8
a,b,c,d
e,f,g,h ²²²²ר─

Ответы [ 4 ]

0 голосов
/ 10 мая 2018

относительно:

printf("%s", content);

код, который заполнил содержимое content, не смог NUL завершить этот массив символов.

(и в выделенной памяти недостаточно места для добавления NUL-символа)

так что вызов printf() будет продолжать выводить символы, пока не найдет NUL-символ.

Это основная причина вывода ненужных символов.

0 голосов
/ 08 мая 2018

Ваша строка не заканчивается нулем. Вам нужно выделить достаточно места для хранения последнего нулевого символа, например, temp = realloc(array, (size + 1) * sizeof(char));, и в конце сделать что-то вроде content[size] = '\0'. Однако использование realloc, вероятно, является худшим способом сделать то, что вы пытаетесь сделать.

Я бы использовал stat, чтобы найти размер файла, затем использовал mmap, чтобы сопоставить файл с памятью, а затем malloc с размером файла, а затем memcpy с malloc ed. объем памяти. realloc это зло, мудрость исполнения.

Вот альтернатива, которая значительно превосходит исходный код:

#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc,char** argv){
    if (argc != 2){
      printf("Usage: %s {filename}\n",argv[0]);
      return 1;
    }
    int fd = open(argv[1], O_RDONLY);
    // @todo: check if fd is valid
    struct stat st;
    int ret = fstat(fd,&st);
    // @todo: check ret
    void* mapped_memory = mmap(NULL,st.st_size,PROT_READ,MAP_SHARED,fd,0);
    // @todo: check mapped_memory that is not null
    char* str = (char*)malloc(sizeof(char)*(st.st_size + 1));
    // @todo: check that str is not null
    memcpy(str,mapped_memory,st.st_size);
    str[st.st_size] = '\0';
    printf("%s",str);
    free(str);
    munmap(mapped_memory,st.st_size);
    close(fd);
    return 0;
}
0 голосов
/ 08 мая 2018

Добавить нулевой завершающий символ в конце:

int size = 0;
int ch = 0;
char* content = 0;
FILE* fs = fopen(file, "r");
//getting file's content and put it into a string
while ((ch = fgetc(fs)) != EOF)
{
    size++;
    content = myRealloc(content, size);
    content[size - 1] = (char)ch;
}
size++;
content = myRealloc(content, size);
content[size - 1] = '\0';
print("%s", content);

Редактировать: Также, как указал @achal, вы пытаетесь добавить символ EOF, поскольку, когда вы читаете его, вы уже находитесь в цикле while. Я изменил свой код соответственно.

0 голосов
/ 08 мая 2018

Оператор ch = (char)fgetc(fs); в цикле также пытается вывести EOF, чего не следует делать.

Просто замените этот блок кода на

while ( (ch = fgetc(fs)) != EOF) { /* fetch the char & check the condition */
      putchar(ch);
      size++;
      content = myRealloc(content, size);
      content[size - 1] = ch;
}
size++;
content = myRealloc(content, size);
content[size - 1] = '\0';
print("%s", content);

Также проверьте страницу руководства fgetc(), она возвращает int. Так что ch введите как int.

 int fgetc(FILE *stream);

Также print("%s", content); должно быть printf("%s", content);, если вы не определили print().

Наконец, и самое главное, когда работа выполнена, не забудьте освободить динамически выделенную память, вызвав функцию free().

...