wananzuiqingfen 发表于 2021-12-6 21:55:05

scanf 函数读入字符串存储至二维数组,访问字符串时非预期结果

我正在编写程序试图颠倒句子中单词的顺序:
Enter a sentence: you can cage a swallow can't you?
Reversal of sentence: you can't swallow a cage can you?
我的想法是使用一个二维数组存储单词字符串,通过一个循环使用 scanf 函数读入单词。

每次读入单词时判断单词的最后一个字符是否是终止字符(. ? !)

如果是,则将最后一次读入的单词末尾字符更换为空字符('\0')后结束循环。

然后逆序打印二维数组中的字符串:
#include <stdio.h>
#include <string.h>

#define WORD_NUMBER 30
#define WORD_LENGTH 20

int main(void)
{
    char ch, terminator, *p;
    char words;

    printf("Enter a sentence: ");
   
    p = words;
    while (1) {
      scanf("%s", p);

      // 判断读入字符串的最后一个字符是否是终止符
      ch = p;
      if (ch == '.' || ch == '?' || ch == '!') {
            terminator = ch;
              p = '\0';
              break;
      }
      p++;
    }

    // 逆序打印单词
    printf("Reversal of sentence:");
    for (; p >= words; p--)
      printf(" %s", p);
    printf("%c\n", terminator);
   
    return 0;
}
输出的结果并不是如我预期的那样逆序输出单词:
Enter a sentence: you can cage a swallow can't you?
Reversal of sentence: you cyou scyou ascyou cascyou ccascyou yccascyou?
我不理解是什么情况导致了字符串的后缀是 cyou。

拜托各位大佬指点一下错误的地方,感激不尽,谢谢~{:5_100:}

jhq999 发表于 2021-12-6 22:05:02

本帖最后由 jhq999 于 2021-12-6 22:26 编辑

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

#define WORD_NUMBER 30
#define WORD_LENGTH 20

int main(void)
{
    char ch, terminator, *p;
    char words;

    printf("Enter a sentence: ");
   
    p = words;
    while (1) {
      scanf("%s", p);

      // 判断读入字符串的最后一个字符是否是终止符
      ch = p;
      if (ch == '.' || ch == '?' || ch == '!') {
            terminator = ch;
                p = '\0';
                break;
      }
        p = '\0';
      p+=strlen(p)+1;
               
    }

    // 逆序打印单词
    printf("Reversal of sentence:");
    for (; p >= words; p--)
                if(*(p-1)==0||words==p)printf(" %s", p);

    printf("%c\n", terminator);
   
    return 0;
}

wananzuiqingfen 发表于 2021-12-6 22:23:50

jhq999 发表于 2021-12-6 22:05


输出更乱了:
Enter a sentence: you can cage a swallow can't you?
Reversal of sentence: you 'you n'you an'you can'you ocan'you locan'you llocan'you allocan'you wallocan'you swallocan'you gswallocan'you agswallocan'you cagswallocan'you acagswallocan'you cacagswallocan'you ocacagswallocan'you yocacagswallocan'you?
我的理解是指针 p 自增会移动到二维数组中的下一个一维数组
代码:
p+=strlen(p)-1;
会使指针指向当前单词的末尾字符

jhq999 发表于 2021-12-6 22:25:15

wananzuiqingfen 发表于 2021-12-6 22:23
输出更乱了:

我的理解是指针 p 自增会移动到二维数组中的下一个一维数组


没想到要改好几个地方

wananzuiqingfen 发表于 2021-12-6 22:29:50

jhq999 发表于 2021-12-6 22:05


感谢,输出符合预期了,明天研究一下,晚安{:5_100:}

jhq999 发表于 2021-12-6 22:39:21

本帖最后由 jhq999 于 2021-12-6 22:41 编辑

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

#define WORD_NUMBER 30
#define WORD_LENGTH 20

int main(void)
{
    char ch, terminator,count=0;
    char words;

    printf("Enter a sentence: ");
    while (1) {
      scanf("%s", words);

      // 判断读入字符串的最后一个字符是否是终止符
      ch =words)-1];
      if (ch == '.' || ch == '?' || ch == '!') {
                        words)-1]='\0';
            terminator = ch;
            break;
      }
         count++;      
    }

    // 逆序打印单词
    printf("Reversal of sentence:");
    for (; count>=0; count--)printf(" %s", words);

    printf("%c\n", terminator);
   
    return 0;
}

jackz007 发表于 2021-12-6 22:40:20

#include <stdio.h>

int main(void)
{
      char c , s                              ;
      int i , j , n                                 ;
      printf("Enter a sentence : ")                   ;
      gets(s)                                       ;
      for(n = 0 ; s ; n = i) {
                for(; s && s < 0x21 ; n ++)       ;
                for(i = n ; s && s > 0x20 ; i ++) ;
                for(j = 0 ; j < (i - n) / 2 ; j ++) {
                        c = s                ;
                        s = s         ;
                        s = c                  ;
                }
      }
      for(i = 0 ; i < n / 2 ; i ++) {
                c = s                        ;
                s = s                     ;
                s = c                              ;
      }
      printf("Reversal of sentence : %s\n" , s)       ;
}
      编译、运行实况:
D:\00.Excise\C>g++ -o x x.c

D:\00.Excise\C>x
Enter a sentence : you can cage a swallow can't you?
Reversal of sentence : you? can't swallow a cage can you

D:\00.Excise\C>

阿萨德按时 发表于 2021-12-7 08:28:12

{:10_254:}

wananzuiqingfen 发表于 2021-12-7 08:41:33

错误之处在于对指针的运用,指针 p 初始指向了二维数组的第一个元素(一个一维数组,实际就是指向了这个一维数组的第一个元素)。
语句:
p++;将二维数组展开看成是一个一维数组,它们的内存地址是连续的,且由于 p 不是指向数组的指针,因此 p++; 只是简单的移动到了下一个内存地址上,这也是造成错误的根源。{:5_100:}{:5_100:}{:5_100:}

改进后的程序如下:
#include <stdio.h>
#include <string.h>

#define WORD_NUMBER 30
#define WORD_LENGTH 20

int main(void)
{
    char ch, terminator, *p;
    char words;

    printf("Enter a sentence: ");
   
    p = words;
    while (1) {
      scanf("%s", p);

      // 判断读入字符串的最后一个字符是否是终止符
      ch = p;
      if (ch == '.' || ch == '?' || ch == '!') {
            terminator = ch;
            p = '\0';
            break;
      }
      p += WORD_LENGTH;
    }

    // 逆序打印单词
    printf("Reversal of sentence:");
    for (; p >= words; p -= WORD_LENGTH)
      printf(" %s", p);
    printf("%c\n", terminator);
   
    return 0;
}

wananzuiqingfen 发表于 2021-12-7 08:47:17

jackz007 发表于 2021-12-6 22:40
编译、运行实况:

大师{:5_100:}{:5_100:}{:5_100:}

1molHF 发表于 2021-12-7 08:52:49

{:10_256:}

15873314901 发表于 2021-12-7 13:33:24

1

伽羅~ 发表于 2021-12-7 13:37:55

{:10_254:}

tianlai7266 发表于 2021-12-7 13:42:24

{:10_254:}

sampsom 发表于 2021-12-7 20:44:12

萌新学习,谢谢大佬,大佬真好!

hornwong 发表于 2021-12-7 22:31:09

感谢分享!

ohhohh 发表于 2021-12-8 15:17:29

{:10_264:}

1279378101 发表于 2021-12-16 14:49:30

页: [1]
查看完整版本: scanf 函数读入字符串存储至二维数组,访问字符串时非预期结果