鱼C论坛

 找回密码
 立即注册
查看: 1420|回复: 17

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

[复制链接]
发表于 2021-12-6 21:55:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我正在编写程序试图颠倒句子中单词的顺序:
  1. Enter a sentence: you can cage a swallow can't you?
  2. Reversal of sentence: you can't swallow a cage can you?
复制代码

我的想法是使用一个二维数组存储单词字符串,通过一个循环使用 scanf 函数读入单词。

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

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

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

  3. #define WORD_NUMBER 30
  4. #define WORD_LENGTH 20

  5. int main(void)
  6. {
  7.     char ch, terminator, *p;
  8.     char words[WORD_NUMBER][WORD_LENGTH+1];

  9.     printf("Enter a sentence: ");
  10.    
  11.     p = words[0];
  12.     while (1) {
  13.         scanf("%s", p);

  14.         // 判断读入字符串的最后一个字符是否是终止符
  15.         ch = p[strlen(p)-1];
  16.         if (ch == '.' || ch == '?' || ch == '!') {
  17.             terminator = ch;
  18.                 p[strlen(p)-1] = '\0';
  19.                 break;
  20.         }
  21.         p++;
  22.     }

  23.     // 逆序打印单词
  24.     printf("Reversal of sentence:");
  25.     for (; p >= words[0]; p--)
  26.         printf(" %s", p);
  27.     printf("%c\n", terminator);
  28.    
  29.     return 0;
  30. }
复制代码

输出的结果并不是如我预期的那样逆序输出单词:
  1. Enter a sentence: you can cage a swallow can't you?
  2. Reversal of sentence: you cyou scyou ascyou cascyou ccascyou yccascyou?
复制代码

我不理解是什么情况导致了字符串的后缀是 cyou。

拜托各位大佬指点一下错误的地方,感激不尽,谢谢~
最佳答案
2021-12-6 22:05:02
本帖最后由 jhq999 于 2021-12-6 22:26 编辑
  1. #include <stdio.h>
  2. #include <string.h>

  3. #define WORD_NUMBER 30
  4. #define WORD_LENGTH 20

  5. int main(void)
  6. {
  7.     char ch, terminator, *p;
  8.     char words[WORD_NUMBER][WORD_LENGTH+1];

  9.     printf("Enter a sentence: ");
  10.    
  11.     p = words[0];
  12.     while (1) {
  13.         scanf("%s", p);

  14.         // 判断读入字符串的最后一个字符是否是终止符
  15.         ch = p[strlen(p)-1];
  16.         if (ch == '.' || ch == '?' || ch == '!') {
  17.             terminator = ch;
  18.                 p[strlen(p)-1] = '\0';
  19.                 break;
  20.         }
  21.         p[strlen(p)] = '\0';
  22.         p+=strlen(p)+1;
  23.                
  24.     }

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

  29.     printf("%c\n", terminator);
  30.    
  31.     return 0;
  32. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-6 22:05:02 | 显示全部楼层    本楼为最佳答案   

回帖奖励 +5 鱼币

本帖最后由 jhq999 于 2021-12-6 22:26 编辑
  1. #include <stdio.h>
  2. #include <string.h>

  3. #define WORD_NUMBER 30
  4. #define WORD_LENGTH 20

  5. int main(void)
  6. {
  7.     char ch, terminator, *p;
  8.     char words[WORD_NUMBER][WORD_LENGTH+1];

  9.     printf("Enter a sentence: ");
  10.    
  11.     p = words[0];
  12.     while (1) {
  13.         scanf("%s", p);

  14.         // 判断读入字符串的最后一个字符是否是终止符
  15.         ch = p[strlen(p)-1];
  16.         if (ch == '.' || ch == '?' || ch == '!') {
  17.             terminator = ch;
  18.                 p[strlen(p)-1] = '\0';
  19.                 break;
  20.         }
  21.         p[strlen(p)] = '\0';
  22.         p+=strlen(p)+1;
  23.                
  24.     }

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

  29.     printf("%c\n", terminator);
  30.    
  31.     return 0;
  32. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-12-6 22:23:50 | 显示全部楼层

输出更乱了:
  1. Enter a sentence: you can cage a swallow can't you?
  2. 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 自增会移动到二维数组中的下一个一维数组
代码:
  1. p+=strlen(p)-1;
复制代码

会使指针指向当前单词的末尾字符
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-6 22:25:15 | 显示全部楼层
wananzuiqingfen 发表于 2021-12-6 22:23
输出更乱了:

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

没想到要改好几个地方
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-12-6 22:29:50 | 显示全部楼层

感谢,输出符合预期了,明天研究一下,晚安
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-6 22:39:21 | 显示全部楼层
本帖最后由 jhq999 于 2021-12-6 22:41 编辑
  1. #include <stdio.h>
  2. #include <string.h>

  3. #define WORD_NUMBER 30
  4. #define WORD_LENGTH 20

  5. int main(void)
  6. {
  7.     char ch, terminator,count=0;
  8.     char words[WORD_NUMBER][WORD_LENGTH+1];

  9.     printf("Enter a sentence: ");
  10.     while (1) {
  11.         scanf("%s", words[count]);

  12.         // 判断读入字符串的最后一个字符是否是终止符
  13.         ch =words[count][strlen(words[count])-1];
  14.         if (ch == '.' || ch == '?' || ch == '!') {
  15.                         words[count][strlen(words[count])-1]='\0';
  16.             terminator = ch;
  17.             break;
  18.         }
  19.          count++;      
  20.     }

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

  24.     printf("%c\n", terminator);
  25.    
  26.     return 0;
  27. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-6 22:40:20 | 显示全部楼层

回帖奖励 +5 鱼币

  1. #include <stdio.h>

  2. int main(void)
  3. {
  4.         char c , s[1024]                                ;
  5.         int i , j , n                                   ;
  6.         printf("Enter a sentence : ")                   ;
  7.         gets(s)                                         ;
  8.         for(n = 0 ; s[n] ; n = i) {
  9.                 for(; s[n] && s[n] < 0x21 ; n ++)       ;
  10.                 for(i = n ; s[i] && s[i] > 0x20 ; i ++) ;
  11.                 for(j = 0 ; j < (i - n) / 2 ; j ++) {
  12.                         c = s[i - 1 - j]                ;
  13.                         s[i - 1 - j] = s[n + j]         ;
  14.                         s[n + j] = c                    ;
  15.                 }
  16.         }
  17.         for(i = 0 ; i < n / 2 ; i ++) {
  18.                 c = s[n - 1 - i]                        ;
  19.                 s[n - 1 - i] = s[i]                     ;
  20.                 s[i] = c                                ;
  21.         }
  22.         printf("Reversal of sentence : %s\n" , s)       ;
  23. }
复制代码

        编译、运行实况:
  1. D:\00.Excise\C>g++ -o x x.c

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

  5. D:\00.Excise\C>
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-7 08:28:12 | 显示全部楼层

回帖奖励 +5 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-12-7 08:41:33 | 显示全部楼层
错误之处在于对指针的运用,指针 p 初始指向了二维数组的第一个元素(一个一维数组,实际就是指向了这个一维数组的第一个元素)。
语句:
  1. p++;
复制代码
将二维数组展开看成是一个一维数组,它们的内存地址是连续的,且由于 p 不是指向数组的指针,因此 p++; 只是简单的移动到了下一个内存地址上,这也是造成错误的根源。

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

  3. #define WORD_NUMBER 30
  4. #define WORD_LENGTH 20

  5. int main(void)
  6. {
  7.     char ch, terminator, *p;
  8.     char words[WORD_NUMBER][WORD_LENGTH+1];

  9.     printf("Enter a sentence: ");
  10.    
  11.     p = words[0];
  12.     while (1) {
  13.         scanf("%s", p);

  14.         // 判断读入字符串的最后一个字符是否是终止符
  15.         ch = p[strlen(p)-1];
  16.         if (ch == '.' || ch == '?' || ch == '!') {
  17.             terminator = ch;
  18.             p[strlen(p)-1] = '\0';
  19.             break;
  20.         }
  21.         p += WORD_LENGTH;
  22.     }

  23.     // 逆序打印单词
  24.     printf("Reversal of sentence:");
  25.     for (; p >= words[0]; p -= WORD_LENGTH)
  26.         printf(" %s", p);
  27.     printf("%c\n", terminator);
  28.    
  29.     return 0;
  30. }
复制代码

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-12-7 08:47:17 | 显示全部楼层
jackz007 发表于 2021-12-6 22:40
编译、运行实况:

大师
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-7 08:52:49 | 显示全部楼层

回帖奖励 +5 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-7 13:33:24 | 显示全部楼层

回帖奖励 +5 鱼币

1
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-7 13:37:55 | 显示全部楼层

回帖奖励 +5 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-7 13:42:24 | 显示全部楼层

回帖奖励 +5 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-7 20:44:12 | 显示全部楼层

回帖奖励 +5 鱼币

萌新学习,谢谢大佬,大佬真好!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-7 22:31:09 | 显示全部楼层

回帖奖励 +5 鱼币

感谢分享!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-8 15:17:29 | 显示全部楼层

回帖奖励 +5 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-16 14:49:30 From FishC Mobile | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-14 16:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表