ИМХО, вы плохо используете функцию strtok()
. Он будет разбивать строку на подстроки каждый раз, когда находит точку .
, t
или x
. Поскольку вы написали код, я боюсь, что это не то, что вы хотите (чтобы исключить суффикс .txt
?)
Прочтите справочную страницу strtok()
, так как там объясняется, что на самом деле делает эта функция.
С другой стороны, вы не можете обрезать строку в начале .txt
, а затем добавить к ней более длинную строку. Когда вы объявили массив str[]
(явно не используя длину), компилятор зарезервировал столько символов для хранения текста, поступающего из макроса, плюс еще один для хранения разделителя \0
. Таким образом, в вашем массиве есть место только для 10 символов (9 из "hello.txt"
плюс один для конца строки '\0'
). Конечно, там нет места для хранения hello_decripted.txt
, для которого потребовалось бы 19 символов плюс еще один для \0
. Обходной путь для этой проблемы может состоять в том, чтобы указать в объявлении массива, сколько символов вы хотите, чтобы компилятор использовал, например:
char str[100] = ENCRYPTED_FILE;
а затем вы можете расширить до 100 символов (99 плюс держатель для конца строки char \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;
}
Это решит проблему с соблюдением ваших намерений. Но вы ошибаетесь в другом:
Что делать, если строка .txt
появляется непосредственно перед концом исходного имени? На мой взгляд, то, что вы ищете, это суффикс .txt
(то, что ранее было известно как расширение). Что мешает вашему файлу назвать что-то вроде blahblah.txt01.txt
? --который имеет два вхождения подстроки .txt
--) Это неправильный алгоритм для поиска суффикса .txt
. Правильный способ — искать, если .txt
находится в конце строки, и для этого используется другой алгоритм (и гораздо более эффективный):
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);
};
в этом случае вам нужно выполнить только одно сравнение строк (которое выполняется несколько раз в теле strstr()
для поиска полного совпадения), и вы быстро и эффективно узнаете, сработает оно или нет.
Примечание
Последнее замечание о строке #include "string.h"
в вашем коде: включение файла с двойными кавычками вместо пары символов <>
допустимо, если у вас есть локальный файл (в вашем локальном каталоге), который называется так же, как какой-либо библиотечный файл, потому что это заставит его быть найденным перед системной библиотекой. Но это плохая привычка, если вы включаете включаемый файл стандартной библиотеки, потому что, если вы позже решите создать включаемый файл (в другом модуле или программе) и создать локальный string.h
файл, эта программа вдруг начнет компилироваться с ошибками, и вы не угадаю почему. Будьте осторожны с #include
именами и двумя способами их вызова. Файлы с именем <file.h>
обычно являются стандартными файлами включения библиотек и ищутся в фиксированных местах в системе. Файлы с именем "file.h"
сначала ищутся в рабочем каталоге, а если не найдены, то ищутся в фиксированных путях библиотеки. Попробуйте использовать "
только для ваших файлов или файлов, которые есть в вашем каталоге сборки, и ищите системные файлы только с <
и >
.
person
Luis Colorado
schedule
03.01.2021
str
? Как долго струна может держаться? - person Mat   schedule 02.01.2021