K&R Упражнение 1-19 неочакван и непоследователен резултат

Работих върху K&R упражнение 1-19:

Напишете програма, която обръща своя вход ред по ред.

Написа следната програма:

#include <stdio.h>
#define MAXLINE 1000

main () {
    int c, x, y, z;
    char ip[MAXLINE];
    char ln[MAXLINE];
    char rv[MAXLINE];

    for (x = 0;(c=getchar()) != EOF; ++x)       
        ip[x] = c;

    for (x = 0; ip[x] != '\0'; ++x) {               
        for (y = 0; ip[x] != '\n'; ++y) {           
            ln[y] = ip[x];
            ++x;
        }

        for (z = 0; y != -1; ++z) {                 
            rv[z] = ln[y];
            --y;
        }
        printf("%s\n", rv);                         
    }
}

Проблемът ми е, че изходът на тази програма е изключително непоследователен; даден същия (многоредов) вход, понякога ще отпечата всеки ред наобратно с добавено водещо празно пространство, понякога ще възпроизведе само първия ред наобратно, последван от празни редове, понякога ще отпечата боклук, а понякога просто получавам съобщение за грешка.

Някой сблъсквал ли се е с такъв вид волатилност преди, без да промени кода си? Как да го поправя?


person Nathaniel Lindsey    schedule 24.02.2016    source източник
comment
Последния път публикувахте доста свързани въпроси. Моля, обмислете използването на различна (и по-нова - C се разви много след последното актуализиране на K&R) книга и/или урок. stack overflow не е сайт за уроци.   -  person too honest for this site    schedule 25.02.2016
comment
Помислете за това, във вашия втори цикъл вие тествате за нулеви знаци в ip. Зададохте ли нулевия знак, когато го прочетохте?   -  person Jeff Mercado    schedule 25.02.2016
comment
Вие четете целия вход в буфер от 1000 байта, без да проверявате дали входът е повече от 1000 байта. Не сте '\0' прекратили ip низа, но x цикълът търси ip[x] != '\0'. И не сте поставили '\0' в края на низа rv, което означава, че printf ще премине края на низа.   -  person user3386109    schedule 25.02.2016
comment
силно препоръчваме да четете само един ред наведнъж за обработка. Това означава, че първият цикъл for() също трябва да проверява за \n, за да намери края на реда. И същият този цикъл трябва да проверява броя на знаците в реда, така че входният буфер да не бъде препълнен.   -  person user3629249    schedule 25.02.2016
comment
в C има само много малко валидни подписи за main() Всички те имат тип на връщане и (освен ако не работите на гола машина без OS, този тип на връщане ще бъде int   -  person user3629249    schedule 25.02.2016
comment
когато пишете код: 1) следвайте аксиомата: само един оператор на ред и (най-много) една декларация на променлива на оператор. 2) използвайте смислени имена на променливи. Т.Е. имена, които показват употреба или съдържание (или по-добре) и двете.   -  person user3629249    schedule 25.02.2016


Отговори (1)


Ако правите K & R, бих ви препоръчал да си купите "C Answer Book", който съдържа всички отговори на своите упражнения.

Опитайте тази:

#include <stdio.h>

#define MAX_LINE 1024

void discardnewline(char s[])
{
  int i;
  for(i = 0; s[i] != '\0'; i++)
  {
    if(s[i] == '\n')
      s[i] = '\0';
  }
}

int reverse(char s[])
{
  char ch;
  int i, j;

  for(j = 0; s[j] != '\0'; j++)
  {
  }

  --j;

  for(i = 0; i < j; i++)
  {
    ch   = s[i];
    s[i] = s[j];
    s[j] = ch;
    --j;
  }

  return 0;
}

int getline(char s[], int lim)
{
  int c, i;

  for(i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
  {
    s[i] = c;
  }

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

  s[i] = '\0';

  return i;

}

int main(void)
{
  char line[MAX_LINE];

  while(getline(line, sizeof line) > 0)
  {
    discardnewline(line);
    reverse(line);
    printf("%s\n", line);
  }
  return 0;
}

Част от него е от книгата, но дори направих свои собствени модификации.

person Ashish Ahuja    schedule 25.02.2016