C 函数,该函数修改字符串并返回修改后的字符串
我有一个从宏中提取字符串的函数。它修改字符串,然后返回一个新修改的字符串。我的意图是使用这个返回的字符串。但是,它不起作用,因为它不返回修改过的字符串C 函数,该函数修改字符串并返回修改后的字符串,c,concatenation,c-strings,function-definition,C,Concatenation,C Strings,Function Definition,我有一个从宏中提取字符串的函数。它修改字符串,然后返回一个新修改的字符串。我的意图是使用这个返回的字符串。但是,它不起作用,因为它不返回修改过的字符串 #include <stdio.h> #include "string.h" #define ENCRYPTED_FILE "hello.txt" char *decrypt(){ char str[]=ENCRYPTED_FILE; strtok(str,".t
#include <stdio.h>
#include "string.h"
#define ENCRYPTED_FILE "hello.txt"
char *decrypt(){
char str[]=ENCRYPTED_FILE;
strtok(str,".txt");
strcat(str,"_decrypted.txt");
//printf("%s\n",str);
return str;
};
int main()
{
printf("%s\n",decrypt()); //output: *** stack smashing detected ***: ./a.out terminated
return 0;
}
#包括
#包括“string.h”
#定义加密的_文件“hello.txt”
char*decrypt(){
char str[]=加密的_文件;
strtok(str,“.txt”);
strcat(str,“_decrypted.txt”);
//printf(“%s\n”,str);
返回str;
};
int main()
{
printf(“%s\n”,decrypt());//输出:**检测到堆栈崩溃***:./a.out终止
返回0;
}
您返回一个指向临时数组的指针,该数组在控件离开函数后变为悬空。首先,您必须通过malloc
在堆上分配它,然后,确保其分配的大小足以包含原始大小加上额外的“\u decrypted”后缀。对于初学者,函数返回指向本地数组str
的第一个元素的指针,该指针具有自动存储持续时间,在退出函数后将不活动
因此,函数返回一个无效指针
您需要为阵列动态分配内存
还有这个调用strtok
strtok(str,".txt");
没有道理。该函数不搜索子字符串“.txt”
。它搜索字符串“.txt”
指定的字符集的第一个字符。相反,您可以使用函数strstr
而此代码strcat
strcat(str,"_decrypted.txt");
调用未定义的行为,因为目标数组没有足够的空间来存储附加的字符串文字
例如,该函数看起来就像下面的演示程序中所示
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ENCRYPTED_FILE "hello.txt"
char *decrypt( void )
{
const char *encrypted_file = ENCRYPTED_FILE;
const char *p = strstr( encrypted_file, ".txt" );
if ( p == NULL ) p = encrypted_file + strlen( encrypted_file );
size_t n = p - encrypted_file;
const char *decrypted_file = "_decrypted.txt";
char *s = malloc( n + strlen( decrypted_file ) + 1 );
memmove( s, encrypted_file, n );
s[n] = '\0';
strcat( s + n, decrypted_file );
return s;
}
int main(void)
{
char *s = decrypt();
puts( s );
free( s );
return 0;
}
我刚刚注意到您的库符号是
#include“string.h”
,而不是#include
,这可能会解决问题。我想您是在错误地使用strok()
函数。每当它找到一个点
、一个t
或一个x
时,它都会将一个字符串拆分为子字符串。由于您已经编写了代码,恐怕这不是您想要的(要消除.txt
后缀?)
阅读strtok()的手册页,因为它将准确解释此函数的实际功能
另一方面,您不能截断.txt
开头的字符串,然后向其追加更长的字符串。当您声明str[]
数组时(通过明确不使用长度),编译器保留尽可能多的字符来保存宏中的文本提交,再加上一个字符来保存\0
分隔符。因此,您的数组只有容纳10个字符的空间(《代码》“hello.txt”中的9个字符,加上字符串末尾的一个字符)。当然,这里没有地方可以容纳需要19个字符加上一个字符的\0
。解决此问题的一种方法是在数组声明中指出希望编译器使用的字符数,如:
char str[100] = ENCRYPTED_FILE;
然后可以扩展最多100个字符(99个字符加上字符串结尾字符的保持符\0
)
如果找到要搜索的字符串(.txt
),并在其第一个位置放置一个\0
,则会截断原始字符串,并可以执行实际需要的操作,即:
#include <stdio.h>
#include <stdlib.h>
#include "string.h" /* is this what you actually mean and not <string.h>? */
#define ENCRYPTED_FILE "hello.txt"
char *decrypt(){
char str[100]=ENCRYPTED_FILE;
char *p = strstr(str,".txt");
if (p != NULL) { /* the string actually has a .txt suffix */
*p = '\0'; /* string truncated */
}
strcat(str,"_decrypted.txt"); /* add new suffix */
//printf("%s\n",str);
/* you cannot return str as str is a local variable,
* and it will cease to exist as soon as we leave this
* function body, better return a new dynamically
* allocated string (that need to be freed with free(3)
*/
return strdup(str);
};
int main()
{
/* the stack smashing probably is due to returning the
* address of a local variable, that ceased to exist.
*/
char *name = decrypt();
printf("%s\n", name);
free(name); /* return the memory allocated in decrypt() */
return 0;
}
在这种情况下,您只需进行一次字符串比较(在strstr()
的主体中多次进行比较,以搜索完整匹配),就可以知道它是否会快速有效地失败
注
关于代码中的
#include“string.h”
行的最后一点注意事项:如果您有一个本地文件(在本地目录中)被称为与某个库文件相同,则可以使用双引号而不是一对
字符来包含该文件,因为这样可以在系统库文件之前找到该文件。但是,如果您包含标准库include文件,这是一个坏习惯,因为如果您以后决定创建一个include文件(在其他模块或程序中)并创建一个本地string.h
文件,该程序将突然开始编译,并出现错误,您猜不出原因。注意#包括
姓名和两种称呼方式。名为
的文件通常是标准的库包含文件,在系统中的固定位置进行搜索。名为“file.h”
的文件首先在工作目录中搜索,如果未找到,则在库固定路径中搜索。试着只对你的文件或你在构建目录中的文件使用”
,只使用
搜索系统文件问:str的大小是多少?它能容纳多长的字符串?大到足以容纳“hello\u decrypted.txt”字符串。你认为这到底是为什么?我现在增大了字符串的大小[40]=加密的_文件;仍然错误
#include <stdio.h>
#include <stdlib.h>
#include "string.h" /* is this what you actually mean and not <string.h>? */
#define ENCRYPTED_FILE "hello.txt"
char *decrypt(){
char str[100]=ENCRYPTED_FILE;
char *p = strstr(str,".txt");
if (p != NULL) { /* the string actually has a .txt suffix */
*p = '\0'; /* string truncated */
}
strcat(str,"_decrypted.txt"); /* add new suffix */
//printf("%s\n",str);
/* you cannot return str as str is a local variable,
* and it will cease to exist as soon as we leave this
* function body, better return a new dynamically
* allocated string (that need to be freed with free(3)
*/
return strdup(str);
};
int main()
{
/* the stack smashing probably is due to returning the
* address of a local variable, that ceased to exist.
*/
char *name = decrypt();
printf("%s\n", name);
free(name); /* return the memory allocated in decrypt() */
return 0;
}
char *decrypt(){
char str[100]=ENCRYPTED_FILE;
char *suff = ".txt";
/* go to the point that is strlen(str) further than
* the beginning of the string minus the string
* of the suffix */
char *p = str + strlen(str) - strlen(suff);
if (strcmp(p, suff) == 0) { /* the string actually has a .txt suffix */
*p = '\0'; /* string truncated */
}
/* from this point on, everything goes the same */
strcat(str,"_decrypted.txt"); /* add new suffix */
//printf("%s\n",str);
return strdup(str);
};