如何从c字符串中读取特定数量的字符?

如何从c字符串中读取特定数量的字符?,c,string,C,String,使用intsnprintf(字符*str,大小\u t大小,常量字符*格式,…) 我可以将特定数量的字符写入str 如何从c字符串中读取特定数量的字符 关于您可以在format参数中传递一个数字: char buf[21]; sscanf(str, "%20s", buf); 这会将最多20个字符读入buf 如果不知道编译时要读取多少数据,可以在运行时准备格式字符串: char format[20]; sprintf(format, "%%%ds", howMuchToRead); sscan

使用
intsnprintf(字符*str,大小\u t大小,常量字符*格式,…)
我可以将特定数量的字符写入
str

如何从c字符串中读取特定数量的字符


关于

您可以在format参数中传递一个数字:

char buf[21];
sscanf(str, "%20s", buf);
这会将最多20个字符读入
buf

如果不知道编译时要读取多少数据,可以在运行时准备格式字符串:

char format[20];
sprintf(format, "%%%ds", howMuchToRead);
sscanf(str, format, buf);

您可以使用
strncpy
memcpy
。但是,请注意,在某些情况下,
strncpy
可能不会追加终止的
'\0'
字符,而且
memcpy
永远不会追加。另外,
memcpy
根本不检查字符串的结尾,它只是复制您请求它的字节数。

您可以使用
sscanf

int sscanf(const char *str, const char *format, ...);
例如:

char out[4];
sscanf("foo", "%3s", &out);
当然,你也可以做一些更有趣的事情:

int value;
sscanf("value=10", "value=%d", &value);

sscanf
scanf
功能一样,存在问题。正如GNU手册所说:

对于给定的格式说明符,必须有足够的地址参数;如果不是这样,结果是不可预测的,很可能是灾难性的

因此,您需要避免一个问题(编译器无法为您验证是否传递了正确数量或类型的参数,尽管有些编译器有专门针对这些函数的警告)。这个问题的一部分还在于,您需要硬编码格式字符串中的最大缓冲区大小(这使得使用整数常量来防止缓冲区溢出更加困难)

因为您的用例只是从一个字符串中复制到一定数量的字符,所以我只使用Joachim Pileborg的答案建议的
strncpy
(并确保设置一个终止的
'\0'
)。对于长度参数,您应该使用输入和输出缓冲区的最小长度减去1以适应终止
nul

换句话说(未经测试):

其中
MIN(a,b)
等同于
a
关于整数。

除了这两种方法和解决方案之外,您还可以使用精度说明符(例如
“%.20s”
仅打印20个字符)。中讨论了C字符串的精度说明符。这些步骤基本上与在
sscanf
解决方案中相同,您可以创建一个格式字符串并使用它捕获所需的字符。
在使用
sscanf
时,如果您使用上述格式说明符,即
%20s”
等,则不能保证如果字符串包含空格,您将获得20个字符;如果遇到空白,则只能在空白之前获取字符(因为空白是
scanf
函数系列的分隔符)。相反,您应该使用类似于
%20[^\n]
的东西<代码>[^\n]
表示直到换行时才读取,而20指定要扫描的字符数。所有这些都可以从以下方面看出:

#包括
#包括
内部主(空){
字符格式[20]={0};
char buf[50]={0};
char str[]=“你好,世界!你好吗?”;
大小\u t howMuchToRead=8;
/*使用sscanf-直到指定空白或大小*/
snprintf(格式,大小格式,“%%%zus”,howMuchToRead);
sscanf(str,格式,buf);
printf(“使用%%8s格式的sscanf:%s\n”,buf);
/*使用sscanf-阅读所有内容直到换行*/
snprintf(格式,大小格式,“%%%zu[^\n]”,howMuchToRead);
sscanf(str,格式,buf);
printf(“使用%%8[^\\n]格式的sscanf:%s\n”,buf);
/*使用精度说明符*/
snprintf(格式,sizeof格式,“%%.%zus”,howMuchToRead);
snprintf(buf,sizeof buf,format,str);
printf(“使用精度说明符:%s\n”,buf);
返回0;
}
/*
输出:
使用%8s格式的sscanf:Hello
使用具有%8[^\n]格式的sscanf:Hello Wo
使用精度说明符:Hello Wo
*/
并提出一些非常重要的要点,你应该注意这些要点。

希望这有帮助

你说的“从c字串读取”到底是什么意思?如果您已经有了字符串,您只需访问数组(考虑nul终止符)并读取您想要的任何内容+1@betabandido这个问题没有太多的解决方案:)@dasblinkenlight:问题是我从用户那里得到了一个变量
size\u t howmuchtoard。我可以将其与您的解决方案结合起来吗?@ron当然可以,您可以在运行时准备格式(请参阅上一次编辑的示例)。编译器无法验证
sscanf
调用参数(尽管有些编译器会发出警告)。我想说,sscanf是以静态类型安全性为代价来解决这一问题的完全过度。
strncpy(dest, src, 
        MIN(NUM_OF_CHARS_TO_COPY, 
            MIN(DEST_BUFFER_SIZE, SRC_BUFFER_SIZE)) - 1);
#include <stdio.h>
#include <string.h>

int main(void) {
        char format[20] = {0};
        char buf[50] = {0};
        char str[] = "Hello World! How are you?";
        size_t howMuchToRead = 8;

        /* Using sscanf - till whitespace or size specified */
        snprintf(format, sizeof format, "%%%zus", howMuchToRead);
        sscanf(str, format, buf);
        printf("Using sscanf with %%8s format :%s\n", buf);

        /* Using sscanf - read everything upto newline */
        snprintf(format, sizeof format, "%%%zu[^\n]", howMuchToRead);
        sscanf(str, format, buf);
        printf("Using sscanf with %%8[^\\n] format :%s\n", buf);

        /* Using precision specifier */
        snprintf(format, sizeof format, "%%.%zus", howMuchToRead);
        snprintf(buf, sizeof buf, format, str);
        printf("Using precision specifier :%s\n", buf);
        return 0;
}
/*
Output:
Using sscanf with %8s format :Hello
Using sscanf with %8[^\n] format :Hello Wo
Using precision specifier :Hello Wo
*/