2016-02-16 4 views
0

Я пытаюсь прочитать файл и строки следующую строку, чтобы увидеть, если она начинается с пробела, например:Использование strcat для конкатенации строк из файла

First line 
second line 
Third line 
fourth line 

Где, когда я читаю файл в, я хочу проверить и посмотреть, есть ли следующая строка, имеет пробел, если это так, я хочу, чтобы strcat две строки (в этом случае первая и вторая строка).

Таким образом, для первого примера:

1.) Читать в первой строке, читайте дальше ко второму, видят, что их пространство, и strcat обе строки, что делает "First linesecond line" (Повторите эти действия для других линий, следуйте этой схеме).

Вот мой пойти на это:

int main(void) { 
    FILE * file = fopen("file.txt","r"); 

    if(file==NULL) { return 0; } 

    char * fileBuffer = malloc(sizeof(char)*100); 
    char * temp = malloc(sizeof(char)*100); 

    while(fgets(fileBuffer,100,file) != NULL) { 
     if(isspace(fileBuffer[0])) { 

      strcpy(temp,fileBuffer); 

      //store line that has a space in static temporary variable 
     } 
     else { 
      if(strcmp(temp,"") != 0) { //if temp is not empty 
       strcat(fileBuffer,temp); 
      } 
     } 
    } 
    free(fileBuffer); 
    free(temp); 

    return 0; 
} 

Однако это не работает. Что происходит, когда fgets выполняется, он читает первую строку, видит, что нет пробела, а затем переходит к следующей строке, видит, что есть пробел, сохраняет его, но теперь fileBuffer больше не содержит первую строку , а второй.

Так что, когда я буду в следующий раз, я не получу правильный результат «Первая строка второй линии».

Вместо этого я получаю результат третьей линии, смешанной со вторым, что не то, что я хочу.

Я не совсем уверен, как исправить мою логику здесь, любые идеи?

+0

использование 'MemSet()' для установки 'fileBuffer' к 0 как последний оператор цикла while. –

+1

'temp' может быть недостаточно большим, чтобы держать весь файл' fileBuffer' –

+0

Я исправил выделение для temp. Также Sourav Я не совсем уверен, что вы подразумеваете под «в последнем цикле». – TTEd

ответ

2

исправить вашу логику так:

#define LINE_SIZE 100 

int main(void) { 
    FILE * file = fopen("file.txt","r"); 

    if(file==NULL) { perror("fopen"); return -1; } 

    char * fileBuffer = malloc(LINE_SIZE); 
    char * temp = malloc(LINE_SIZE * 2);//Binding of the string is only once 

    while(fgets(fileBuffer, LINE_SIZE, file) != NULL) { 
     if(isspace(fileBuffer[0])) { 
      temp[strcspn(temp, "\n")] = 0;//remove newline 
      strcat(temp, &fileBuffer[1]); 
      printf("%s", temp); 
     } 
     else { 
      strcpy(temp, fileBuffer); 
     } 
    } 
    fclose(file); 
    free(fileBuffer); 
    free(temp); 

    return 0; 
} 
+0

Итак, в инструкции if здесь & fileBuffer [1] - следующая строка в коде? – TTEd

+0

@TTEd Чтобы перейти к началу символа пробела. если вы хотите '' Первая строка второй строки'', измените '& fileBuffer [1]' на 'fileBuffer' – BLUEPIXY

+0

@BLUEPIXY. Для начинающих на этом сайте, пожалуйста, объясните **, что ** вы изменили. – SevenBits

1

У вас есть несколько дополнительных соображений, с которыми вам придется иметь дело. Первое, вам нужно удалить трейлинг-код '\n', включенный в число прочитанных fgets. Для этого вам потребуется длина строки. Затем вы можете удалить пробную версию '\n', переписав ее нуль-оканчивающимся символом. например:

while (fgets (buf1, MAXC, fp)) { 
    size_t len1 = strlen (buf1); /* get length */ 
    if (len1 && buf1[len1-1] == '\n') buf1[--len1] = 0; /* remove \n */ 

Другое соображение заключается в том, как управлять распределением и освобождением памяти, которую вы используете для комбинированной линии. Так как вы читаете первую часть, а затем вторую часть вашей последней строки из строк с фиксированной длиной, было бы разумнее использовать 2 статических буфера, один для чтения строки и один для хранения копии первый. Вы можете выделить итоговый результат. например

enum { MAXC = 100 }; /* constant for max characters */ 
... 
int main (int argc, char **argv) { 

    char buf1[MAXC] = {0}; 
    char buf2[MAXC] = {0}; 
    char *both = NULL; 

После того, как обе части вашей линии готовы к объединению, вы можете выделить точно необходимое пространство, например.

 if (*buf1 == ' ' && *buf2) { 
      both = malloc (len1 + strlen (buf2) + 1); 
      strcpy (both, buf2); 
      strcat (both, buf1); 
      ... 

Не забудьте freeboth после каждого распределения. Ввод куски вместе, и фиксируя логику ваших сравнений, вы могли бы в конечном итоге с раствором, как следующее:

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

enum { MAXC = 100 }; 

int main (int argc, char **argv) { 

    char buf1[MAXC] = {0}; 
    char buf2[MAXC] = {0}; 
    char *both = NULL; 
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; 
    if (!fp) { 
     fprintf (stderr, "error: file open failed '%s'.\n,", argv[1]); 
     return 1; 
    } 

    while (fgets (buf1, MAXC, fp)) { 
     size_t len1 = strlen (buf1); 
     if (len1 && buf1[len1-1] == '\n') buf1[--len1] = 0; 
     if (*buf1 == ' ' && *buf2) { 
      both = malloc (len1 + strlen (buf2) + 1); 
      strcpy (both, buf2); 
      strcat (both, buf1); 
      printf ("'%s'\n", both); 
      free (both); 
      *buf2 = 0; 
     } 
     else 
      strcpy (buf2, buf1); 
    } 
    if (fp != stdin) fclose (fp); 

    return 0; 
} 

Выход

$ ./bin/cpcat ../dat/catfile.txt 
'First line second line' 
'Third line fourth line' 

Посмотрите его и дайте мне знать, если вы есть вопросы.

+0

Уверен, что вы знаете, что я не вентилятор 'fgets (buf1, MAXC, fp)) {size_t len1 = strlen (buf1); buf1 [len1-1] = 0; 'поскольку это хакерский эксплойт, чтобы первый символ' char' 'fgets()' читал нулевой символ. [другие идеи] (http://stackoverflow.com/q/2693776/2410359) Кроме того, последняя строка файла может не иметь \ n – chux

+1

Да, я ценю это. Цель заключалась не в том, чтобы зайти слишком далеко от конкатенации кроликов. Однако вы на 100% правильны. Должна быть включена общая проверка 'if (len1)' и нормальные проверки последнего символа, являющегося «новой строкой», должны быть там. Исправлено ':)' –

0

Действительно быстрый и грязный способ

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

int main(void) { 

    FILE * file = fopen("file.txt", "r"); 

    if (file == NULL) { return 0; } 

    char fileBuffer[100]; 
    char temp[100]; 
    int first = 1; 

    while (fgets(fileBuffer, 100, file) != NULL) { 
     if (isspace(fileBuffer[0])) { 

      strcat(temp, fileBuffer); 
      //store line that has a space in static temporary variable 
     } 
     else { 
      if (first == 1){ 
       strncpy(temp, fileBuffer, sizeof(temp)); 

       // Remove the end line 
       temp[strlen(temp) - 1] = 0; 
       strcat(temp, " "); 
       first = 0; 
      } 
      else{ 
       if (strcmp(temp, "") != 0) { //if temp is not empty 
        strcat(temp, fileBuffer); 

        // Remove the end line 
        temp[strlen(temp) - 1] = 0; 
        strcat(temp, " "); 
       } 

      } 

     } 
    } 
    printf("%s", temp); 
    free(fileBuffer); 
    free(temp); 

    return 0; 
} 

Выход: enter image description here

+0

'char temp [100]; ... strcat (temp, fileBuffer); 'concatenates в неинициализированный массив' temp'. – chux

+0

При первом запуске strncpy (temp, fileBuffer, sizeof (temp)); – HoKy22

+0

Это «первый раз, когда он идет на strncpy», происходит только в том случае, если первая строка не начинается с пробела. что-то вне контроля кода. – chux