| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4335 人关注过本帖
标题:用scanf读入一串数据,但遇到逗号就出现未知错误。
只看楼主 加入收藏
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:0 
回复 10楼 vvvcuu
所以说,scanf语句他并没有智能到可以用逗号作为分隔符,
以下是引用书生牛犊在2015-10-31 15:20:43的发言:

补充这个程序的目的
:题目内容:
  编写程序,在主函数中定义一个有10个元素的整型一维数组,用户输入9个数据,调用函数,对数组元素进行从小到大排序后,在函数中输入一个数,插入到数组中正确的位置,并输出。
输入格式:
  9个整数和1个整数
输出格式:
  10个整数
输入样例:
2,3,1,5,6,76,89,31,90[回车]
7[回车]
输出样例:
1,2,3,5,6,7,31,76,89,90[回车]
——————————————————————————————
上一次遇到这种用逗号隔开的数据,我在scanf里面用两个%d夹着一个%c,蒙混过关。可是这一次给了九个数据,我要是还一个个去夹%c,就太对不起这门语言了。所以才会特别想要知道,这里面的问题根源是什么。去测试数据,也没搞懂

所以,对于这样的题目,我还是需要先从屏幕获取字符串,然后通过逐个对比,运用一些手段去生成这个数组。
        我还想着会不会已经有了通用的解决方案了呢,
慕课网上的答题已经应付过关了……还是把九个输入用一句
scanf("%d,%d,%d,%d,%d,%d,%d,%d,%d",&b[0],&b[1],&b[2],&b[3],&b[4],&b[5],&b[6],&b[7],&b[8]);
写完,怎么感觉这么笨嘞……

[此贴子已经被作者于2015-10-31 20:24编辑过]


φ(゜▽゜*)♪
2015-10-31 20:23
vvvcuu
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:12
帖 子:353
专家分:1253
注 册:2014-4-22
收藏
得分:0 
回复 11楼 书生牛犊
楼主, 建议重新拜读Tony Deng版主在二楼的回复:
以下是引用TonyDeng在2015-10-31 14:06:25的发言:

scanf()函數命名中的f,是format的首字母,即“格式化”,意思是說,這個函數的功能是通過掃描(scan)被格式化(format)過的字符串提取數據。要跳過不需要的字符,用scanf("%d,", &x),它的意圖是,讀入一個整數後,順帶掃過一個逗號,也就是說,你的輸入中必須在整數後面帶一個逗號,此逗號是略過不要的,但輸入中必須有,注意最後也需要逗號——這種掃描法始於C程序專門編寫從格式文本數據流中讀入數據,一般編製文本文件時都有這類統一的格式化間隔符。

爲什麽平時有人寫scanf("%d,%d", &a, &b)這類的代碼,在運行時經常出現問題呢?就是因爲他實際輸入的動作跟scanf()格式指示串"%d,%d"預期的不符,他沒有在兩個整數之間輸入逗號,那麽scanf()函數在讀入第一個整數之後掃描不到逗號,就影響後面的提取,於是運行出現毛病。這種問題,在編譯時是檢查不出來的,scanf()/printf()之類函數,雖然説是C的常用函數,但其機制本身卻與C語言靜態強類型檢查的特點截然相反,屬於典型的動態運行時函數,那本來是BASIC之類語言的優勢。


注意里面的这一句代码:
scanf("%d,", &x)


请观察一下和下面这句的不同:
scanf("%d", &x)


双引号里面就是控制格式的, 里面的除了格式控制字符,其它字符你在输入的时候如果不按照它的规定输入系统就会报错. %d后面跟了逗号,那么你输入的时候分隔就要用逗号,不然scanf一直等不到你的逗号, 要么执行出错, 要么就一直等待.

代码测试环境:  WinXP+C-Free5.0.
2015-10-31 22:59
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:0 
回复 13楼 vvvcuu
这个我理解了,scanf语句应该是尽可能简洁为好,这样尽可能少的去给用户添加限制会使程序的健壮性更强。
程序代码:
#include<stdio.h>
main()
{int a,b=5,c=5;
scanf("%d%d%d",&a,&b,&c); 
printf("%d,%d,%d",a,b,c);
}

好像这样形式的scanf,他在读入的时候就是默认使用空格或者回车作为分隔符来分别读入数据。而这里一旦输入逗号他也是分辨不了的,读不到数据。
----------------------------------------------------------------
我也在百度上找过其他的屏幕输入语句:好像gets之类的。但都没有直接能帮助我转换数据的,都是先读入字符串,再自行编程转换。

φ(゜▽゜*)♪
2015-11-01 01:01
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:0 
回复 13楼 vvvcuu
就好像加入我在编译的时候,手欠在scanf语句里加了什么提示性字词啊,

    等程序编译完成,交付使用的时候,用户就会很头疼了。
        
        因为他输入的时候就必须和我scanf里的格式一模一样(包括全半角、数据类型等)。

所以我们非常有必要慎重对待这类scanf语句,引号里面的部分能不多写绝不赘述。引号后面的要跟一个指向地址的变量(通常也都是用&指针。)

φ(゜▽゜*)♪
2015-11-01 01:08
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
程序代码:
/*
题目内容:编写程序,在主函数中定义一个有10个元素的整型一维数组,用户输入9个数据,调用函数,对数组元素进行从小到大
排序后,在函数中输入一个数,插入到数组中正确的位置,并输出。

输入格式:
9个整数和1个整数

输出格式:
10个整数

输入样例:
2,3,1,5,6,76,89,31,90[回车]
7[回车]

输出样例:
1,2,3,5,6,7,31,76,89,90[回车]
*/

#include <stdio.h>
#include <conio.h>

#define NUMBER    10

// 暫停程序等待用戶按鍵
void Pause(void)
{
    printf_s("\nPress any key to continue...");
    _getch();
}

// 交換兩個數據
void swap(int* x, int* y)
{
    int temp = *x;
    *x = *y;
    *y = temp;
}

// 輸出指定數組的内容
void List_Data(const int* data, unsigned int size)
{
    for (unsigned int index = 0; index < size; ++index)
    {
        printf_s("%d", data[index]);
        if (index < size - 1)
        {
            putchar(',');
        }
    }
    putchar('\n');
}

// 用冒泡法升序排序指定數組
void Sort(int* data, unsigned int size)
{
    for (unsigned int i = 0; i < size - 1; ++i)
    {
        for (unsigned int j = i; j < size; ++j)
        {
            if (data[i] > data[j])
            {
                swap(&data[i], &data[j]);
            }
        }
    }
}

// 將指定數據插入已排序數組中
void Insert(int x, int* data, unsigned int size)
{
    unsigned int index;
    for (index = size - 1; (index > 0) && (x < data[index - 1]); --index)
    {
        data[index] = data[index - 1];
    }
    data[index] = x;
}

int main(void)
{
    int data[NUMBER], x;

    printf_s("Input:\n");
    for (unsigned int index = 0; index < NUMBER - 1; ++index)
    {
        scanf_s("%d ,", &data[index]);
    }
    scanf_s("%d", &x);
#ifdef _DEBUG
    printf_s("--------------------\n");
    printf_s("Your input:\n");
    List_Data(data, NUMBER - 1);
    printf_s("%d\n", x);
    printf_s("After on Sort:\n");
    Sort(data, NUMBER - 1);
    List_Data(data, NUMBER - 1);
    printf_s("--------------------\n");
#endif

    printf_s("Output:\n");
    Insert(x, data, NUMBER);
    List_Data(data, NUMBER);

    Pause();
    return 0;
}


運行畫面:
图片附件: 游客没有浏览图片的权限,请 登录注册


[此贴子已经被作者于2015-11-1 04:18编辑过]


授人以渔,不授人以鱼。
2015-11-01 03:34
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
再看另一個運行畫面
图片附件: 游客没有浏览图片的权限,请 登录注册

授人以渔,不授人以鱼。
2015-11-01 03:37
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
注意scanf()的格式指示符是"%d ,"用各種不同的輸入方式多運行幾次,就明白我逗號前面的空格是有道理的。描紅的文字,是編程者必須要做的功夫,不要養成衹運行一次得到需要的結果就了事的習慣,尤其是某些人故意避開自己設計的缺陷去湊動作的。

[此贴子已经被作者于2015-11-1 04:25编辑过]


授人以渔,不授人以鱼。
2015-11-01 04:21
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
在弄明白這個程序的第一版本之後,不妨想一下:現在設定了NUMBER的10,如果它是100、1000怎麽辦?難道你每次都用手指敲入這龐大的數據?實際上,單是現在的10,在反復運行不同輸入方式的時候,你就已經會意識到這個問題,因爲此時你要保證每次輸入的數據包括順序都一樣(變化的衹是逗號、空格、回車的數量和位置),才能測試出當前設計方案能否應付不同的情景。

想想吧,再想想我爲什麽會設計那些函數,爲什麽要那樣的傳參,如何使用。多問幾個爲什麽,多設想幾個如果遇到什麽、該怎麽辦,比做大量的題目強。

授人以渔,不授人以鱼。
2015-11-01 04:31
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:0 
回复 19楼 TonyDeng
今天的课程讲到了scanf语句,尤其是提到了怎样解决逗号的问题。

scanf语句里面有一个特殊参数叫“*”这个字符表示读入到该数据时忽略不要。所以,对于整篇帖子所要解决的问题,有这样一种解法:


scanf("%d%*c",a[i]);//这里运用了%*c来忽略掉一个未知的字符,从而达到即可以分辨出逗号、顿号、甚至小数点(我测试过了,如果我前面是%d,那么我输入12.34 55.62他所能读入的就是四个数,分别是12,34,55,62.没有小数。)


----------------
我就说嘛,使用人数这么多、使用范围这么广的一种语言,他怎么会解决不了一个逗号的问题呢!哈哈,果然还是我见识的不够多啊~~

φ(゜▽゜*)♪
2015-11-02 13:58
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:0 
回复 19楼 TonyDeng
我还是没有看懂那个“%d空格,”的奥秘。
        我在计算机上运行你的程序,确实达到了效果,可以辨认出逗号来,也可以空格、回车。

但是我在自己写了一个简单的输入输出程序去验证,却发现我写的scanf(“%d ,%d”)语句还是要求我输入的两个数之间必须有逗号。我要是输入空格,他就读到1(是不是乱码我就不知道了)。
        我今天刚刚学到“*”的用法,感觉还是比较适用的,可以同时处理空格、顿号、逗号、回车、等一系列数字以外的字符(只支持半角字符,如果顿号用中文输入,那也会导致出错,如何解决尚未知。)。附上运行图示
程序代码:
#include <stdio.h>
#include <conio.h>
int main(){
    int a,b;
    for(int i=0;i<5;i++)
    {scanf("%d%*c%d",&a,&b);
    printf("%d %d\n--------------第%d次测试---------\n",a,b,i);
    }
    return 0;
}

图片附件: 游客没有浏览图片的权限,请 登录注册

φ(゜▽゜*)♪
2015-11-02 14:33
快速回复:用scanf读入一串数据,但遇到逗号就出现未知错误。
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.029072 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved