我需要查找所有出现并输出字符串中子字符串的所有位置。
例如:我的字符串是abaaab
,我的子字符串是aa
,位置是3
和4
,因为在aaa
我的substr重复了两次
我希望最后的位置从右到左打印,在子字符串的位置后我想要我的子串的出现次数。
我试着去做,我有这个:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char *str, c;
int x = 0, y = 1;
str = (char*)malloc(sizeof(char));
printf("Inserisci stringa principale : ");
while (c != '\n') {
// read the input from keyboard standard input
c = getc(stdin);
// re-allocate (resize) memory for character read to be stored
str = (char*)realloc(str, y * sizeof(char));
// store read character by making pointer point to c
str[x] = c;
x++;
y++;
}
str[x] = '\0'; // at the end append null character to mark end of string
printf("\nLa stringa inserita : %s", str);
char *sub, b;
int w = 0, z = 1;
sub = (char*)malloc(sizeof(char));
printf("Immetti sottostringa da cercare : ");
while (b != '\n') {
// read the input from keyboard standard input
b = getc(stdin);
// re-allocate (resize) memory for character read to be stored
sub = (char*)realloc(sub, z * sizeof(char));
// store read character by making pointer point to c
sub[w] = b;
w++;
z++;
}
sub[w] = '\0'; // at the end append null character to mark end of string
char *p1, *p2, *p3;
int i=0,j=0,flag=0;
p1 = str;
p2 = sub;
for(i = 0; i<strlen(str); i++)
{
if(*p1 == *p2)
{
p3 = p1;
for(j = 0;j<strlen(sub);j++)
{
if(*p3 == *p2)
{
p3++;p2++;
}
else
break;
}
p2 = sub;
if(j == strlen(sub))
{
flag = 1;
printf("\nSottostringa trovata all'indice : %d\n",i);
}
}
p1++;
}
if(flag==0)
{
printf("Sottostringa non trovata");
}
free(str);
free(sub);
return (0);
}
但它只显示第一次出现的位置,而不是出现次数。
答案 0 :(得分:2)
您的代码中存在多个问题:
您的字符串重新分配方案不正确:分配的空间对于字符串来说太短了一个字节,您永远不会测试内存分配失败。如果您的系统支持getline()
,或者至少编写一个函数来分解代码,您可以使用c
。
c != '\n'
时, #include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* read an allocated string from stream.
stop at newline, not included in string.
Return NULL upon EOF
*/
char *my_getline(FILE *stream) {
char *line = NULL;
size_t pos = 0;
int c;
while ((c = getc(stream)) != EOF) {
char *newp = realloc(line, pos + 2);
if (newp == NULL) {
free(line);
return NULL;
}
line = newp;
if (c == '\n')
break;
line[pos++] = (char)c;
}
if (line) {
line[pos] = '\0';
}
return line;
}
int main(void) {
char *str, *sub;
size_t len1, len2, i, count = 0;
// type the main string
printf("Inserisci stringa principale :\n");
str = my_getline(stdin);
// type the substring to search for
printf("Immetti sottostringa da cercare :\n");
sub = my_getline(stdin);
if (str && sub) {
len1 = strlen(str);
len2 = strlen(sub);
for (i = 0; i + len2 <= len1; i++) {
if (!memcmp(str + i, sub, len2)) {
count++;
// substring found at offset
printf("Sottostringa trovata all'indice : %zu\n", i);
}
}
if (count == 0) {
// substring not found
printf("Sottostringa non trovata\n");
}
}
free(str);
free(sub);
return 0;
}
未初始化:这有未定义的行为。
您的匹配算法过于复杂:您同时使用索引值和移动指针。使用其中一种。
这是一个简化版本:
strstr()
注意:
上面的代码在搜索字符串中的每个偏移处找到空子字符串的匹配项。是否应该找到匹配是一个规范问题,但这种行为与strstr()
的行为一致。
您还可以使用标准函数strstr()
来查找匹配项。
以下是使用if (str && sub) {
for (char *p = str; (p = strstr(p, sub)) != NULL; p++) {
count++;
// substring found at offset
printf("Sottostringa trovata all'indice : %tu\n", p - str);
if (*p == '\0') /* special case for the empty string */
break;
}
if (count == 0) {
// substring not found
printf("Sottostringa non trovata\n");
}
}
的主循环版本:
assert_no_difference 'User.count' do
post users_path, params: { user: { name: "",
email: "user@invalid",
password: "foo",
password_confirmation: "bar" } }
end
答案 1 :(得分:1)
我检查了你的代码,似乎你的代码在行中有问题
if(j == strlen(sub))
由于j从0开始,它总是比子字符串的长度小1,将代码更改为
if(j+1 == strlen(sub))
它应该可以解决你的问题。
对于出现次数,只要与子字符串匹配,就需要计算另一个变量,修改if块
if(j+1 == strlen(sub))
{
flag = 1;
occurrences+=1; //declare variable occurrences and initialize it to 0
printf("\nSottostringa trovata all'indice : %d\n",i);
}
然后在循环结束后,只需打印'occurrence'以获得所需的结果。
这也不是解决问题的有效方法,您可以参考
更好的方法。
答案 2 :(得分:0)
查找每个事件的一种简单方法是在循环中调用strstr
。每次比赛结束后,让strstr
搜索找到匹配项后的一个位置:
int main( ) {
const char *string = "abaaab";
const char *toSearch = "aa";
int nrOfOccurences = 0;
printf("searching for occurences of '%s' in string '%s':\n", string, toSearch);
const char* pos = string;
while (pos) {
pos = strstr(pos, toSearch);
if (pos) {
printf("found occurence at position %td\n", pos-string);
nrOfOccurences++;
pos++; // skip one character
}
}
nrOfOccurences = findRecursive(string, toSearch, 0,0);
printf("nr of occurences: %d\n", nrOfOccurences);
return 0;
}
如果你需要 - 以某种方式说明 - 从最后一个开始打印出现的事件,你可以使用如下的递归函数。上面代码中的注释显示了如何使用它:
int findRecursive(const char* str, const char* toSearch, ptrdiff_t pos, int nrOfOccurences) {
char *next = strstr(str, toSearch);
if (next) {
ptrdiff_t foundPos = pos + next - str;
nrOfOccurences = findRecursive(next+1, toSearch, foundPos+1, nrOfOccurences+1);
printf("occurence found at position %td\n", foundPos);
}
return nrOfOccurences;
}