我想写一个函数,它将把一个指向char的指针和一个int(扫描开始索引)作为输入,并返回它之后的第一个单词。这个代码有什么问题?没有字返回。创建了从何处包含分隔符之一的问题。涂鸦字符。
char *setWord(char string[], int *n) {
char word[20] = "\0";
string += *n;
while (*string == ','||*string == '\t' || *string == '\n'
|| *string == ' '|| *string == '.' || *string == '!' || *string == '?') {
string++;
(*n)++;
}
int i = 0;
while (*string != ',' && *string != '\t'
&& *string != '\n' && *string != ' ' &&
*string != '.' && *string != '!' &&
*string != '?') {
word[i] = *string;
string++;
(*n)++;
i++;
}
char *words = word;
return words;
}
您希望从函数返回一个C字符串([指向]以null结尾的字符数组的指针)。问题是数组不是C中的第一类对象,所以只能传递和返回指针。任何自动数组都将在声明它的块的末尾达到其生命周期的终点。因此,如果您很好地将word构建成一个自动数组,并返回指向它的指针(当前代码所做的),那么当函数返回时只留下一个悬空的指针,数组就会被破坏。
有两种可能的方法,每种方法都有其优缺点:
>
它可以是递归的和线程安全的。简单地说,您必须记录调用者将负责释放内存块,以及它应该如何完成:如果您使用malloc
,删除[]
如果您使用new[]
。
使用静态记忆
一个快速解决方法是写:
static char word[20];
静态数组将持续到程序结束,因此您可以在调用者中安全地使用它,不需要清理。但是在多线程程序中,静态数组将在所有线程之间共享,因此您必须确保只有一个线程在同一时间使用它,并且当您想要使用它时,另一个线程没有更改它。长话短说:如果该函数预计将在多线程程序中使用,请不要使用该函数。
如注释中所述,由于返回了指向局部变量(words
)的指针,因此没有UB。最初,循环中还有n
,而不是(n*)
,后者也是UB。您需要在代码中进行错误检查,但以下操作仍然有效,并且仍然坚持使用char*
(无错误检查):
#include <string>
#include <iostream>
char *setWord( char string[], int *n ) {
char word[20] = { 0 };
string += *n;
while ( *string == ',' || *string == '\t' || *string == '\n' || *string == ' ' || *string == '.' || *string == '!' || *string == '?' ) {
string++;
( *n )++;
}
int i = 0;
while ( *string != ',' && *string != '\t' && *string != '\n' && *string != ' ' && *string != '.' && *string != '!' && *string != '?' ) {
word[i++] += *string;
string++;
( *n )++;
}
std::cout << word;
char *words = new char[i + 1];
strncpy( words, word, I + 1 );
return words;
}
int main() {
char str[] = "hello world!";
int n = 5;
char *word = setWord( str, &n );
delete[] word;
return 0;
}
使用std::字符串
,可以进行(无错误检查):
std::string setWord( std::string string, int *n ) { // copy on purpose
int start = *n;
*n = string.length();
size_t end = string.find_last_of( ",\t\n .!?" );
string = string.substr( string.find_first_not_of( ",\t\n .!?", start ) );
if ( end != std::string::npos ) {
string = string.substr( 0, string.find_last_of( ",\t\n .!?" ) ); // because it's not end
*n = (int)end;
}
std::cout << string;
return string;
}
主要内容:到底使用字符数组还是字符串常量C语言中没有特定的字符串类型,我们通常是将字符串放在一个字符数组中,这在《 C语言字符数组和字符串》中已经进行了详细讲解,这里不妨再来演示一下: 运行结果: https://www.xnip.cn https://www.xnip.cn 字符数组归根结底还是一个数组,上节讲到的关于 指针和数组的规则同样也适用于字符数组。更改上面的代码,使用指针的方式来输出字符串: 运行结果: https://ww
一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个 指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是 函数指针。 函数指针的定义形式为: returnType (*pointerName)(param list); returnType
问题内容: 有没有机会从以字符串表示的函数名称中获取指向函数的指针?例如,这需要将某些函数作为参数发送给另一个函数。您知道某种元编程。 问题答案: Go函数是一等值。您无需恢复动态语言中的技巧。 操场 输出: 如果函数的选择取决于某些仅在运行时已知的值,则可以使用映射:
我使用的是BennyBox频道上的ECS的一个修改版本(代码可以在这里找到),它在大多数情况下都能正常工作。但是,当我向组件添加std::string时,程序在退出时中止(当ECS类的析构函数被调用时),并显示消息:
在下面的结构中,数组与指向字符的指针相比有什么好处: 或 我看到的一个优点是,使用更容易区分“未提供字符串”和“提供空字符串”,而且它比数组占用更少的空间。 此外,在这两种情况下,我可以初始化: 另一方面,我不能轻易地在上使用,它必须是分配内存上的有效指针。 那么,还有什么好处呢?
本文向大家介绍C语言 函数指针(指向函数的指针)详解,包括了C语言 函数指针(指向函数的指针)详解的使用技巧和注意事项,需要的朋友参考一下 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就