Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中任意数量的空格上拆分字符串_C_File_Parsing - Fatal编程技术网

在C中任意数量的空格上拆分字符串

在C中任意数量的空格上拆分字符串,c,file,parsing,C,File,Parsing,我有一个文件,其中每个用户名和密码由不同数量的空格分隔 bob passowrd1 saly password2 sam password2 void parse() { FILE*open; open = fopen("file.txt"); char line[101]; char*name; char*password; while(fgets(100,line,open)!=NULL) { name

我有一个文件,其中每个用户名和密码由不同数量的空格分隔

bob    passowrd1
saly password2
sam      password2

void parse()
{
    FILE*open;
    open = fopen("file.txt");
    char line[101];
    char*name;
    char*password;

    while(fgets(100,line,open)!=NULL)
    {
       name = strtok(line,"*\\s");
       password = strtok(NULL,"*\\s");
       printf("username : %s",name);
       printf("password : %s",password); 
    }
}

我试图使用strtok拆分字符串,但它不接受regex作为delimeter。我唯一能想到的另一种方法是通过在字符串上进行forloop并在空格后创建两个新的独立字符串来强制执行。有什么建议吗?

你(和大多数受访者)对此想法太多了。strtok()在一个或多个分隔符上进行分隔,因此

name = strtok(line," ");
password = strtok(NULL," ");

将完全执行您想要的操作。

如果可用,您可以使用
strep
(字符串分隔)
strep
接受一组分隔符,并将逐步通过字符串将其分隔为字段。它优于strtok,因为它不保留隐藏的全局状态

void split_fields_strsep( char *string ) {
    char *field;
    const char *delimiters = " \t\n";

    while( (field = strsep(&string, delimiters)) != NULL ) {
        // Multiple spaces will show up as multiple empty fields.
        // Skip them.
        if( *field == '\0' ) {
            continue;
        }

        printf("field: '%s'\n", field);
    }
}
请注意,每个
字段都是指向原始
字符串的指针
strep
将通过在每个字段末尾放置空字节将字符串拆分为字段。如果
string
foobarbaz\0
则以
foo\0bar\0baz\0\0
结尾。因此,如果要保留字符串,请确保
strdup


如果
strep
不可用,则标准
strtok
将起作用。它的工作原理类似于strsep
,将通过添加空字节来更改原始字符串

void split_fields_strtok( char *string ) {
    const char *delimiters = " \t\n";

    for(
        char *field = strtok(string, delimiters);
        field != NULL;
        field = strtok(NULL, delimiters)
    ) {
        printf("field: '%s'\n", field);
    }
}
在C中任意数量的空格上拆分字符串

“*\\s”
表示对如何对令牌字符进行编码存在误解<代码>“*\\s”
查找3个字符
*
\
s
作为标记,与
strtok()
一起使用时,这些字符均不表示空格


使用显式列表解析输入行中的空白。请务必说明输入行或其他空白行的尾随
'\n'

C中的空白包括许多字符:

标准的空白字符如下:空格(
'
)、换页(
'\f'
)、新行(
'\n'
)、回车(
'\r'
)、水平制表符(
'\t'
)和垂直制表符(
'\v'
)。
C11dr§7.4.1.10 2

这个输出

username : <bob>
password : <passowrd1    <-- Oops
>
用户名:

密码:我很担心你为什么要存储明文密码。@tadman这只是一个介绍类,我知道以明文存储密码是不安全的
scanf
函数族忽略了某些格式(如
%s
)的所有前导空格<代码>如果(fscanf(myfile,“%s%s”,name,password)!=2){/*错误输入*/}
是我的第一条评论,更好的解决方案是使用
fgets
读取文件的每一行,然后应用
sscanf
。这使得转储无效条目变得很容易。这里有大量的SO问题和示例代码供您查找。您还没有发布任何尝试,因此问题已脱离主题。“我正在尝试使用strtok拆分字符串,但它不接受regex作为delimeter。”-->发布该代码。没有提供VTC。
strep
正是OP不想要的:它将每个单独的分隔符字符视为一个单独的分隔符。(“strep和strtok_r之间的一个区别是,如果输入字符串在一行中包含来自delimiter的多个字节,strep将为来自delimiter的每对字节返回一个空字符串。”引号来自glibc的信息文件。)<代码>strtok做了正确的事情,但是它的界面很糟糕。如果可能的话,使用@rici I accounted
strep
在代码中的行为,这里有注释和所有内容。我同意strtok,但我想提供一个标准选项,因为许多类都坚持使用C90
strtok_r
至少是POSIX标准的,所以确实是这样,但我发现在分离通常需要保留空字段的单独字段时,
Stresp
更易于使用,也更灵活,尽管不是在这种特殊情况下。在非标准扩展和POSIX标准函数之间,我个人会选择后者,尤其是如果它做了正确的事情。当然,您可能有一个实现附录K
strtok\u
接口的libc。诚然,
strep
非常普遍,但如今
strtok\r
也很普遍。并为没有阅读您的代码而道歉。@rici您应该看到的。;)使用
fgets()
填充
行[]
,此快速答案将包含
'\n'
密码中,因为仅在
上标记“
不足以满足OP的“在空格后创建两个新的单独字符串”要求
  char line[] = "bob    passowrd1\n";
  char*name = strtok(line, " ");
  char* password = strtok(NULL, " ");
  printf("username : <%s>\n", name);
  printf("password : <%s>\n", password);
username : <bob>
password : <passowrd1    <-- Oops
>