不好意思,我在編寫以下程式碼時遇到一些問題,希望有人可以幫忙
我希望程式碼可以讀入一行字串和一 篇文章,
第一行:(字被取代) (字要加入)
例如
第一行:hey hi
文章:hey, They’re just the nice, Hey….
輸出:hi
Thi
另外如果在第一行加上-i ,大小階不同但相同字也會被取代
例如
第一行:hey hi -I
文章:hey, They’re just the nice, Hey….
輸出:hi
Thi
It
如果第一行讀入少於 2個或多於3個字串,或第三個字串不是-i要輸出
輸出:Invalid case
我的做法是分用fget讀取兩行字串
然後分別把單詞除掉符號和空白后,存到陣列(到這?為止應該是正確的)
用strstr查看該詞語中有沒有要找的字
如果有,就把該單詞拆開三分”前””要被取代的字””後”
把目標字取代後,把三個部分都放在同一陣列,後printf出
但是不知為什麼程式碼沒有輸出任可東西
我確定兩行字串中的字詞有正確被分開存到我指定的陣列中,但沒有辨法去找到要找的字
以下是我的程式碼麻煩了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define arrlen 100
#define string_len 4096
// str1_temp 和str2_temp 用來放各自的token
char str1_temp[3][101] = {'\0'}, str1[250] = {'\0'}, str2[4096] = {'\0'}, str2_temp[4096][101] = {'\0'}, temp_of_capital[101] = {'\0'};
char getword_temp[101], result[4096][101] = {'\0'}, old[101], new[101]; //給getword 用
int str1_temp_len = 0, str2_temp_len = 0;
const char delim[] = " !?_\n\t\r:,./[]{}";
void replace(char *p, int pos, char *temp, int new_len, int num, int old_len);
char *getword(char *article, char *word);
int main()
{
// str1_temp_len 和str2_temp_len 代表各自的長度 num=number of token
int str2_temp_x_leght = 0, old_len = 0, new_len = 0, par = 0, temp_len = 0, have_capital; //有要找的字的token的長度 par=0代表沒有parameter
char str2_temp_x[101], parameter[101];
const char delim[] = " !?_\n\t\r:,./[]{}@#$^*()+=_";
int pos = 0, a = 0, b = 0, c = 0, total = 0;
fprintf(stderr, "Enter pattern, replacement, and at most one parameter: ");
fgets(str1, arrlen, stdin);
fprintf(stderr, "Enter the article: ");
fgets(str2, string_len, stdin);
// printf("str1:%s\n",str1);
// printf("str2:%s\n",str2);
str1[strlen(str1) - 1] = '\0';
str2[strlen(str2) - 1] = '\0';
// read string1 string2 [parameter]
char *token1;
token1 = strtok(str1, delim);
// printf("%s",token);
str1_temp_len = 0;
while (token1 != NULL)
{
// vv token ok
//找old ,new,parameter
strcpy(str1_temp[str1_temp_len], token1);
str1_temp_len++; // find str1_temp leght
// printf("str1 token:%s\n",token1);//vv token ok
//續找token
// printf("tokenstr1:%s %d",token1,str1_temp_len);
token1 = strtok(NULL, delim);
if (str1_temp_len < 2 && str1_temp_len > 3)
{
fprintf(stderr, "Invalid case");
break;
}
}
char *ptr;
ptr = str2;
str2_temp_len = 0;
while (ptr = getword(ptr, getword_temp))
{
strcpy(str2_temp[str2_temp_len], getword_temp);
str2_temp_len++;
}
strcpy(old, str1_temp[0]);
strcpy(new, str1_temp[1]);
strcpy(parameter, str1_temp[2]);
// printf("%s %s %s",old,new,parameter);
if (strcmp(parameter, "-i") != 0 && str1_temp_len == 3)
{ //有第三個字串但不是-i
fprintf(stderr, "Invalid case");
}
else
{
par = 1;
} // par=1代表有-i
old_len = strlen(old);
new_len = strlen(new);
///////////////////////////////////////////
//在每個str2的token中找str1_temp[0]
char *p;
int num = 0;
p = (char *)malloc(string_len * sizeof(char));
for (int x = 0; x < str2_temp_len; x++)
{
p = 0;
char temp[101] = {'\0'};
strcpy(temp, str2_temp[x]); //把token放入temp
//找有沒有相同的字
p = strstr(temp, old); //
// printf("%s",p);
///////如果有"-i"
if (par == 1)
{
temp_len = strlen(temp);
//找該token有沒有大階
have_capital = 0;
for (int i = 0; i < temp_len; i++)
{
if (temp[i] >= 'a' && temp[i] <= 'z')
{
}
else
{
have_capital = 1;
}
}
//該token有大階
if (have_capital == 1)
{
strcpy(temp_of_capital, temp);
int i = 0;
//將大階變成小階
while (temp_of_capital[i] == '\0')
{
if (temp_of_capital[i] <= 'Z' && temp_of_capital[i] >= 'A')
{
temp_of_capital[i] += 32;
}
}
p = 0;
p = strstr(temp_of_capital, old); //在temp_of_capital有相同字的位置
replace(p, pos, temp, new_len, num, old_len);
}
}
///////////////////////////////////////////
//如果有要找的字
//應該是從這開始有問題
if (p)
{
int total = 0; //
pos = p - &temp[0];
//找有old前的字完
for (int i = 0; i < pos; i++)
{
result[num][total] = temp[i];
total++;
}
//找有old的位置加入new
for (int i = 0; i < new_len; i++)
{
result[num][total] = new[i];
total++;
}
//加入new後
for (int j = pos + old_len; temp[j] != '\0'; j++)
{
result[num][total] = temp[j]; //將temp的單字放入 result[num]
total++;
}
result[num][total] = '\0';
num++;
}
//初始化temp
for (int i = 0; i < 101; i++)
{
temp[i] = '\0';
}
}
for (int i = 0; i < num - 1; i++)
{
printf("%s", result[i]);
}
return 0;
}
char *getword(char *text, char *temp)
{
char *ptr1 = text;
char *ptr2 = temp;
while (*ptr1 && !isalnum(*ptr1))
{
ptr1++;
}
while (*ptr1 && isalnum(*ptr1))
{
if (ptr2 - temp >= 128)
{
break;
}
*ptr2++ = *ptr1++;
}
*ptr2 = '\0';
if (ptr2 - temp == 0)
{
return NULL;
}
return ptr1;
}
void replace(char *p, int pos, char *temp, int new_len, int num, int old_len)
{
if (p)
{
int total = 0;
num = 0; //
pos = p - &temp[0];
//找有old前的字完
for (int i = 0; i < pos; i++)
{
result[num][total] = temp[i];
total++;
}
//找有old的位置加入new
for (int i = 0; i < new_len; i++)
{
result[num][total] = new[i];
total++;
}
//加入new後
for (int j = pos + old_len; temp[j] != '\0'; j++)
{
result[num][total] = temp[j]; //將temp的單字放入 result[num]
total++;
}
result[num][total++] = '\0';
num++;
for (int i = 0; i < 101; i++)
{
temp[i] = '\0';
}
}
}
告訴你一個好消息和一個壞消息
好消息是我找到為什麼沒有輸出任何東西的原因
以下這段程式碼
在「只輸入兩個字串時(會跑到 else),par 會等於 1」以致出錯
if (strcmp(parameter, "-i") != 0 && str1_temp_len == 3)
{ //有第三個字串但不是-i
fprintf(stderr, "Invalid case");
}
else
{
par = 1;
} // par=1代表有-i
壞消息是我只 debug 到這裡,剩下的實在懶得看了
以下是照你原本程式碼去修的
37~54 行的 while 這樣即可
(這邊我沒看原本的寫法能不能正常跑)
while (token1 != NULL)
{
//str1_temp 最多只能存 3 個詞,多的會被省略
if (str1_temp_len < 3)
{
strcpy(str1_temp[str1_temp_len++], token1);
token1 = strtok(NULL, delim);
}
else
{
fprintf(stderr, "Invalid case");
}
}
70~78 行判斷參數那邊要修一下,不然只輸入 hey hi
也會當作有 -i
if (strcmp(parameter, "-i") == 0 && str1_temp_len == 3)
{
par = 1;
}
else if(str1_temp_len != 2)
{
fprintf(stderr, "Invalid case");
}
88~164 的 for 迴圈弄得太複雜
既然已經有自己寫 replace 函式
可以利用,避免太多重複的程式碼
for (int x = 0; x < str2_temp_len; x++)
{
char temp[101] = {'\0'};
char *pSearchStr;
if (par == 1)
{
//複製 str2_temp[x] 到 temp,並把所有字母轉為小寫
strcpy(temp, str2_temp[x]);
temp_len = strlen(temp);
for (int i = 0; i < temp_len; i++)
{
if ('A' <= temp[i] && temp[i] <= 'Z')
{
temp[i] += 32;
}
}
//搜尋目標為 temp (轉小寫的 str2_temp[x])
pSearchStr = temp;
}
else
{
//搜尋目標為 str2_temp[x]
pSearchStr = str2_temp[x];
}
p = strstr(pSearchStr, old);
strcpy(pSearchStr, str2_temp[x]);
replace(p, pSearchStr, new_len, old_len, &num);
}
replace 函式
因為你要動到那個 num,所以要改成傳址
另外 pos 既然每次都會重新計算,那用區域變數就好,不需要當參數
void replace(char *p, char *temp, int new_len, int old_len, int *num)
{
if (p != NULL)
{
int total = 0, pos;
pos = p - temp;
//找有old前的字完
for (int i = 0; i < pos; i++)
{
result[*num][total] = temp[i];
total++;
}
//找有old的位置加入new
for (int i = 0; i < new_len; i++)
{
result[*num][total] = new[i];
total++;
}
//加入new後
for (int j = pos + old_len; temp[j] != '\0'; j++)
{
result[*num][total] = temp[j]; //將temp的單字放入 result[num]
total++;
}
result[*num][total++] = '\0';
(*num)++;
for (int i = 0; i < 101; i++)
{
temp[i] = '\0';
}
}
}