2015-07-28 2 views
0

Я просматриваю K & R упражнений с самого начала, и я расширяю все, что предназначено для stdin в качестве файла, который должен быть передан как argv. Дело в том, что в этом упражнении функция работает неправильно, я думаю, что это проблема с strlen, но я просто не могу понять, что это на самом деле. Функция правильно меняет строки файла (по-видимому), но я всегда получаю первые два символа первой строки в каждой инвертированной строке. «Напишите функцию reverse, которая меняет символ string s. Используйте его для записи программы, которая меняет направление ввода строки за раз».Упражнения K & R 1-19 переделать для файла, который будет считаться аргументом

#include <stdio.h> 
#include <string.h> 
const unsigned MAXLINE = 10000; 
char* reverse(char string[]) 
{ 
    char rev[MAXLINE]; 
    int i, j; 
    for (i = strlen(string)-1, j = 0; i >= 0, j < strlen(string); --i, ++j) 
      rev[j] = string[i]; 
    return rev; 
} 
unsigned fgetline(char s[], unsigned lim, FILE *file) 
{ 
    unsigned i; 
    char c; 
    for (i = 0; (c = fgetc(file)) != EOF && c != '\n'; ++i) 
      s[i] = c; 
    if (c == '\n') 
    { 
      s[i] = c; 
      ++i; 
    } 
    s[i] = '\0'; 
    return i; 
} 
int main(int argc, char *argv[]) 
{ 
    FILE *input = fopen(argv[1], "r"); 
    char line[MAXLINE]; 
    unsigned len = 0; 
    if (argc != 2 || !input) 
      puts("INSERT VALID INPUT FILE"); 
    else 
    { 
      while ((len = fgetline(line, MAXLINE, input)) > 0) 
      { 
        printf("%s\n", reverse(line)); 
        putchar('\n'); 
      } 
      fclose(input); 
    } 
    return 0; 
} 
+3

Вы возвращаете указатель на локальный буфер в 'реверс()', так что я на самом деле удивлен, это работает на всех. Кроме того, вы забыли обнулить конец «rev» перед возвратом. –

+1

При компиляции всегда включайте все предупреждения. (для gcc, при минимальном использовании: '-Wall -Wextra -pedantic') Затем компилятор расскажет вам о многочисленных проблемах с синтаксисом с опубликованным кодом. После устранения этих проблем предложите использовать отладчик, например gdb (в gcc, используйте параметр «-ggdb» как на этапе компиляции, так и на ссылке, так что выходы gdb очень читаемы) и выполните код – user3629249

+0

, вы также можете изменить строку на месте. Просто поменяйте «символы». Вы не уверены, что строки, считанные 'fgetline', вписываются в' line'. – Rptx

ответ

3

Строка char 'rev' теряет область действия после вызова и поэтому не определена в поведении. Рассмотрим передачу rev в качестве параметра для reverse().

+0

Правильно, вам нужно также обнулить нулевую строку. – Jiminion

+0

Извините, но я этого не понял. Что вы имеете в виду при передаче rev в качестве параметра для обратного, точно? Что он должен вернуть? –

+0

создайте переменную char revline [MAXLINE] в главном. Затем вызовите reverse (line, revline) ;. Ему не нужно ничего возвращать (возможно, успех/неудача). Результаты должны быть отброшены. – Jiminion

1

Я запустил следующий код.

Я компилируется

использует хороший логический порядок настройки работы

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

Я провел его против своего собственного исходного файла.

Я не вижу никаких проблем в результате выходов

#include <stdio.h> 
#include <stdlib.h> // exit(), EXIT_FAILURE 
#include <string.h> 

#define MAXLINE (10000) 

void reverse(char src[], char dest[]) 
{ 
    size_t i; 
    size_t j = 0; 

    memset(dest, '\0', MAXLINE); 

    for (i = strlen(src)-1; i != 0; --i, ++j) 
      dest[j] = src[i]; 
} 


unsigned fgetline(char dest[], FILE *file) 
{ 
    unsigned i; 
    int c; 
    memset(dest, '\0', MAXLINE); 

    for (i = 0; i < (MAXLINE-1) && (c = fgetc(file)) != EOF && c != '\n'; ++i) 
      dest[i] = c; 

    if (c == '\n') 
    { 
      dest[i] = c; 
      ++i; 
    } 

    dest[i] = '\0'; 
    return i; 
} 


int main(int argc, char *argv[]) 
{ 
    if(argc != 2) 
    { 
     printf("USAGE: %s <inputFileName>\n", argv[0]); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, right number of command line parameters 

    FILE *input = NULL; 
    if(NULL == (input = fopen(argv[1], "r"))) 
    { // then fopen failed 
     perror("fopen for input file failed"); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, fopen successful 

    char inputLine[MAXLINE] = {'\0'}; 
    char outputLine[MAXLINE] = {'\0'}; 

    while (fgetline(inputLine, input)) 
    { 
     reverse(inputLine, outputLine); 
     printf("%s\n", outputLine); 
     putchar('\n'); 
    } 

    fclose(input); 

    return 0; 
}