使用sscanf

时间:2016-11-21 16:59:30

标签: c scanf

我正在努力实现这一目标。我读取了一个整数字符串,从该链中提取它们并将它们放在一个数组中。我想尝试新的东西,因为过去常常用getChar字符来阅读字符,但现在我找到sscanf来处理这项工作。

来自Doc(sscanf): 成功时,该函数返回成功填充的参数列表中的项目数。此计数可以匹配预期的项目数,或者在匹配失败的情况下更少(甚至为零)。 如果在成功解释任何数据之前输入失败,则返回EOF。

行:char line[] = "100 185 20 11 1000"; // number of int is unknown, it can differ

问题:如何在行尾和任何错误之间进行差异

例如:char line[] = "100 185 abc(not int) 11 1000";

代码

int main(int argc, char** argv) {

    char line[] = "100 185 20 11 1000";    
    int  arrOfInt[10];
    char *data = line;
    int  track, number, index = 0;

    while ((sscanf(data, " %d%n", &number, &track)) == 1)
    {
        arrOfInt[index] = number;
        data += track;
        index++;
    }
    return 0;
}

3 个答案:

答案 0 :(得分:2)

@BLUEPIXY提到了正确的答案。只是在这里形式化。

如果scanf的返回值为EOF,则表示看到EOF。如果是0,则表示发生了其他错误,并且通过%n设置的值未定义(例如,输入与指定的格式不匹配)。

只要没有带有混合字母的标记和类似" hey45hey2"的字母,以下方法就可以正常工作。

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {

    char line[] = "100 185 20 11 1000 sdf 342 hey45hey2";    
    int  arrOfInt[10];
    char *data = line;
    int  track, status = 0, number, index = 0;

    // read until an EOF is found
    while ((status = sscanf(data, " %d%n", &number, &track)) != EOF)
    {
        // store only if status is non-zero i.e. sscanf has read according to the format specified
        if(status != 0){
            arrOfInt[index] = number;
            index++;
        }
        else
            track=1;
        data += track;
    }
    // print the array back to check if we read correctly
    int i;
    for(i=0;i<index;i++)
    printf("%d ", arrOfInt[i]);
    return 0;
}

此代码的输出为:

100 185 20 11 1000 342 45 2

如果你想排除&#34; hey45hey2&#34;等字符串。从输出中,然后使用以下内容。

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {

    char line[] = " egsdfgfd rgege 100 185 20 11  hey45hey2 0d0  00 sddbrsdtbrtsdbrsf 342";    
    int  arrOfInt[10];
    char *data = line;
    int  track, status = 0, index = 0;
    char str[100]; // will fail for tokens of length more than 100

    // read until an EOF is found
    while ((status = sscanf(data, "%s%n", str, &track)) != EOF)
    {
        // store only if status is non-zero
        if(status != 0){
            // check if str is all zeros
            int num=(int)strtol(str,0,10); 
            char *i = str;
            if(num == 0){
                while(*i){
                    if(*i != '0') break;
                    i++;
                }
            }
            if(*i == 0 || num != 0){
                // if *i is zero, then num is also zero
                arrOfInt[index] = num;
                index++;
            }
        }
        else
            track = 1;
        data += track;
    }
    // print the array back to check if we read correctly
    int i;
    for(i=0;i<index;i++)
    printf("%d ", arrOfInt[i]);
    return 0;
}

输出为100 185 20 11 0 342

答案 1 :(得分:1)

  

如何在行尾和任何错误之间进行差异

很抱歉这样说,但答案是:删除sscanf,然后自行解析。

如果出于某种原因,你需要/想要坚持sscanf可以总是对&#34;字符串进行测试&#34;在sscanf完成后,要查看 if ,在最后一个令牌读取之后还有更多令牌,因为您知道解析的令牌数量。例如,您可以通过在空白处使用strtok预先标记字符串来执行此操作,如果您在少数情况下扫描,则您将字符串指针前进到最后的+ 1标记后继续使用sscanf。但这样理智吗? ; - )

答案 2 :(得分:1)

通过使用您的建议,我实现了我真正想做的事情。只是要提一下,当我发现不受欢迎的角色时,我必须离开我的循环并显示错误。

代码(对其他人有用)

-(void)postToFirebase {

NSMutableDictionary *notifictionDetails = [[NSMutableDictionary alloc] init];
[notifictionDetails setObject:@"possesion" forKey:@"team 1"];
[notifictionDetails setObject:@"userid" forKey:@"id"];

NSMutableDictionary *sdetails = [[NSMutableDictionary alloc] init];
[sdetails setObject:@"high" forKey:@"priority"];
[sdetails setObject:@"my FCM token" forKey:@"to"];
[sdetails setObject:notifictionDetails forKey:@"notification"];

NSLog(@"Required Format Data is %@",sdetails);

NSString *post = [NSString stringWithFormat:@"%@", sdetails];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

NSLog(@"Post Data Is: %@", postData);


NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:@"https://fcm.googleapis.com/fcm/send"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:postLength forHTTPHeaderField:@"Authorization"];
[request setValue:@"key=" forHTTPHeaderField:@"Authorization"];
[request setHTTPBody:postData];

NSLog(@"The Request To Firebase: %@", request);

}