我正在尝试将 1 个字符和 2 个字符串保存到变量中。我使用 sscanf 读取以下形式的字符串:
N "OldName" "NewName"
Run Code Online (Sandbox Code Playgroud)
我想要的: char character = 'N', char* old_name = "OldName", char* new_name = "NewName"。
这就是我尝试这样做的方式:
sscanf(mystring,"%c %s %s",&character,old_name,new_name);
printf("%c %s %s",character,old_name,new_name);
Run Code Online (Sandbox Code Playgroud)
问题是,我的问题在没有任何输出的情况下停止工作。(我也想忽略引号并只保存其内容)
当你这样做时
char* new_name = "NewName";
Run Code Online (Sandbox Code Playgroud)
您使指针new_name指向包含常量字符串文字的只读字符串数组。该数组恰好包含 8 个字符(字符串的字母加上终止符)。
首先,使用该指针作为 for 的目标scanf将导致scanf写入只读数组,从而导致未定义的行为。如果你给出的字符串超过 7 个字符,那么scanf也会尝试越界写入,再次导致未定义的行为。
简单的解决方案是使用实际的数组,而不是指针,并且还告诉scanf不要读取超出数组容量的内容。像这样:
char old_name[64]; // Space for 63 characters plus string terminator
char new_name[64];
sscanf(mystring,"%c %63s %63s",&character,old_name,new_name);
Run Code Online (Sandbox Code Playgroud)
要跳过引号,您有多种选择:使用指针和指针算术来跳过前导引号,然后在最后一个引号的位置设置字符串终止符以“删除”它。另一种解决方案是移动字符串以覆盖前导引号,然后按照之前的解决方案删除最后一个引号。
sscanf(mystring,"%c \"%63s\" \"%63s\"",&character,old_name,new_name);
Run Code Online (Sandbox Code Playgroud)
请注意,如果字符串实际上包含引号,则上述sscanf调用将起作用。
第二个注意事项:正如 Cool Guy 的评论中所说,上述内容实际上不会起作用,因为scanf是贪婪。它将读取直到文件/字符串末尾或空格,因此它实际上不会在结束双引号处停止读取。使用 and family 的唯一有效解决方案scanf是下面的解决方案。
还要注意的是scanf,当读取字符串时,使用"%s"停止读取空白,所以如果字符串是"New Name"那么它也不起作用。如果是这种情况,那么您要么需要手动解析字符串,要么使用奇怪的"%["格式,例如
sscanf(mystring,"%c \"%63[^\"]\" \"%63[^\"]\"",&character,old_name,new_name);
Run Code Online (Sandbox Code Playgroud)