我需要從 C 中的字串中洗掉所有出現的最常見單詞。
如果文本中有多個單詞重復相同的次數,則該函式應洗掉最接近字串開頭的最常見單詞之一。省略單詞時,不應省略周圍的空格和其他字符。如果接收到的字串不包含任何單詞,則函式不需要做任何事情。
單詞被定義為大寫和小寫字母的陣列。該函式不需要區分大小寫字母
我的演算法如下:
- 找出最常見的單詞出現在字串中的次數
- 然后逐字逐句通過字串
- 檢查單詞出現是否等于最常見單詞的出現
- 洗掉找到的最常用詞
代碼:
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
int number_of_word_occurrence(char *s, char *start, char *end) {
int number = 0;
while (*s != '\0') {
char *p = start;
char *q = s;
while (p != end) {
if (*p != *q)break;
p ;
q ;
}
if (p == end)number ;
s ;
}
return number;
}
int length(char *s) {
char *p = s; int number = 0;
while (*p != '\0') {
p ;
number ;
}
return number;
}
char *remove_most_common(char *s) {
int n, max = INT_MIN;
char *p = s;
// Find max occurrence
while (*p != '\0') {
char *start = p;
int word_found = 0;
while (toupper(*p) >= 'A' && toupper(*p) <= 'Z' && *p != '\0') {
word_found = 1;
p ;
}
if (word_found) {
n = number_of_word_occurrence(s, start, p);
if (n > max)max = n;
}
p ;
}
p = s;
int len = length(s);
char *end = s len;
int i;
// Removing most common word
while (p != end) {
char *start = p, *pp = p;
int word_found = 0;
while (toupper(*pp) >= 'A' && toupper(*pp) <= 'Z' && pp != end) {
word_found = 1;
pp ;
}
if (word_found) {
n = number_of_word_occurrence(s, start, pp);
// If word has max, then remove it
if (n == max) {
while (pp != end) {
*start = *pp;
start ;
pp ;
}
end -= max; // resize end of string
len-=max;
}
}
p ;
}
s[len =2]='\0';
return s;
}
int main() {
char s[1000] = "Koristio sam auto-stop da dodjem do znaka stop ali prije stopa sam otvorio dekstop kompjutera stop";
printf("%s ", remove_most_common(s) );
return 0;
}
- 應該洗掉的單詞以粗體顯示
示例 1:“Koristio sam auto- stop da dodjem do znaka stop ali prije stopa sam otvorio dekstop kompjutera stop ”
輸出:“Koristio sam auto- da dodjem do znaka ali prije stopa sam otvorio dekstop kompjutera”
示例 2:“ 這 是字串。”
輸出:“是字串。”
示例 3:“1 PsT 1 psT 2 3 Pst pstpst pst ”;
輸出:““11 2 3 pstpst”
示例 4:“ oneeebigggwwooorrrddd ”;
輸出: ””
你能幫我修復我的代碼嗎?洗掉字符時出現一些錯誤。另外,如果所有單詞出現都相同,您能幫我洗掉最接近開頭的單詞嗎?
- 注意:解決任務時不允許使用 , 庫中
string.h的函式以及 stdio.h 庫中stdlib.h的sprintf和函式。sscanf不允許在函式中或全域創建輔助字串。
uj5u.com熱心網友回復:
所有主要問題都是由于字串是資訊源,同時被積極更改。
一般來說,單詞沒有被正確標記。
以輸入"hello world"為例,在查找要洗掉的單詞時對字串進行標記時,每個hello、ello、llo、lo和o都被視為單詞。程式在掃描單詞時僅將字串前移一個字符。
程式應該將字串推進當前標記的長度。
number_of_word_occurrence在進行比較時,將任何子字串視為有效單詞。
對于輸入
Koristio sam auto- stop da dodjem do znaka stop ali prije stop a sam otvorio dek stop kompjutera stop
錯誤地發現最大計數是5, 對于stop. 此問題與上述問題復合,并開始洗掉報告此發生計數的錯誤標記化資料。
概括地說,這種方法的一個大問題是,當您從字串中洗掉一個單詞時,該單詞的出現次數將會不同,下次找到它時。看著
hello hello hello world world
這里一個單詞的最大出現次數是3,對于hello。回圈洗掉最大的單詞會hello第一次看到,檢查它的出現次數,找到它是3,最大值,然后洗掉它。
hello hello world world
對于第二個hello,現在檢查它的出現計數將回傳2,因為字串已被更改。這不是 的最大值3,因此字串不變。
此外,字串在更改時不會以空值結尾 - 僅在之后。意思是搜索一個詞可能會讀取陳舊的資料,從而產生不好的結果。
對程式可以使用的功能的嚴格限制(特別是對動態記憶體和輔助緩沖區的限制)確實提供了非常詳盡的解決方案。
一種解決方案是首先發現字串count中任何單詞的最大出現次數,并持有指向該單詞在字串中的第一次出現的指標。然后,做counttimes 操作,去掉最后出現的單詞,這樣你就可以始終將第一次出現作為比較點。
通過用字串中緊隨其后的所有內容(包括空終止位元組)覆寫一個單詞來洗掉它。
這是一個粗略的示例 - 很大程度上未經測驗,但為所示示例提供了正確的結果。編譯-DDEBUG以查看更多資訊。
#include <ctype.h>
#include <stdio.h>
typedef struct word {
const char *base;
size_t length;
} word;
#define length(s) (span((s), NULL))
size_t span(const char *base, int (*test)(int))
{
const char *end = base;
while (test ? test((unsigned char) *end) : *end)
end ;
return (size_t) (end - base);
}
int eql(word a, word b)
{
#ifdef DEBUG
fprintf(stderr, "DEBUG: A{%zu}<<%.*s>> <=> B{%zu}<<%.*s>>\n",
a.length, (int) a.length, a.base,
b.length, (int) b.length, b.base);
#endif
if (!a.length || !b.length || a.length != b.length)
return 0;
if (a.base == b.base)
return 1;
for (size_t i = 0; i < a.length; i )
if (tolower((unsigned char) a.base[i]) != tolower((unsigned char) b.base[i]))
return 0;
return 1;
}
word get_word(const char *s, const char **end)
{
word w = { 0 };
while (*s && !isalpha((unsigned char) *s))
s ;
w.base = s;
w.length = span(s, isalpha);
*end = (s w.length);
return w;
}
word find_last(const char *s, word mark, unsigned *count)
{
word last = { 0 };
unsigned c = 0;
for (const char *end; *s; s = end) {
word current = get_word(s, &end);
if (eql(mark, current)) {
last = current;
c ;
}
}
if (count)
*count = c;
return last;
}
word find_most_common(const char *s, unsigned *count)
{
word most_common = { 0 };
*count = 0;
for (const char *end; *s; s = end) {
word current = get_word(s, &end);
if (eql(most_common, current))
continue;
unsigned c;
(void) find_last(s, current, &c);
if (c > *count) {
most_common = current;
*count = c;
}
}
return most_common;
}
void copy(char *dest, char *source, size_t length)
{
for (size_t i = 0; i < length; i )
dest[i] = source[i];
}
void remove_most_common(char *s)
{
unsigned count = 0;
word common = find_most_common(s, &count);
#ifdef DEBUG
if (count)
fprintf(stderr, "DEBUG: MOST COMMON WORD: [[%.*s]]x%u\n",
(int) common.length, common.base, count);
#endif
size_t len = length(s);
while (count--) {
word last = find_last(s, common, NULL);
copy(
(char *) last.base,
(char *) last.base last.length,
len - (size_t) (last.base - s) 1);
len -= last.length;
}
}
int main(void)
{
char buffer[4096];
if (!fgets(buffer, sizeof buffer, stdin))
return 1;
size_t len = length(buffer);
if (len && buffer[len - 1] == '\n')
buffer[len - 1] = 0;
printf("<<%s>>\n", buffer);
remove_most_common(buffer);
printf("<<%s>>\n", buffer);
}
uj5u.com熱心網友回復:
我決定撰寫一個新函式,從字串中洗掉所有出現的單詞,這完全符合您的要求。您只需要提供出處和需要洗掉的單詞即可。
代碼:
#include <stdio.h>
#include <ctype.h> // toupper
#include <string.h> // strlen
#include <stdbool.h> // bool
void removeWord(char* source, char* removeThis)
{
int i, j;
bool wordFound;
int sourceLength, removeLength;
sourceLength = strlen(source);
removeLength = strlen(removeThis);
for(i = 0; i < sourceLength; i)
{
wordFound = true;
for(j = 0; j < removeLength; j)
{
if(toupper(source[i j]) != toupper(removeThis[j]))
{
wordFound = false;
break;
}
}
// It is not a word if the previous character or after the last one is alphabetic
if(wordFound && (isalpha(source[i j]) || (i > 0 && isalpha(source[i - 1]))))
{
wordFound = false;
}
if(wordFound)
{
for(j = i; j <= sourceLength - removeLength; j)
{
source[j] = source[j removeLength];
}
--i;
sourceLength -= removeLength;
}
}
}
int main()
{
char string1[] = "Koristio sam auto-stop da dodjem do znaka stop ali prije stopa sam otvorio dekstop kompjutera stop";
removeWord(string1, "stop");
printf("\n%s", string1);
char string2[] = {"This is string."};
removeWord(string2, "this");
printf("\n%s", string2);
char string3[] = "1PsT1 psT2 3Pst pstpst pst";
removeWord(string3, "pst");
printf("\n%s", string3);
char string4[] = "oneeebigggwwooorrrddd";
removeWord(string4, "oneeebigggwwooorrrddd");
printf("\n%s", string4);
char string5[] = "Tomtom";
removeWord(string5, "tom");
printf("\n%s", string5);
return 0;
}
輸出:
Koristio sam auto- da dodjem do znaka ali prije stopa sam otvorio dekstop kompjutera
is string.
11 2 3 pstpst
Tomtom
基于此,您應該能夠撰寫部分以找到最常用的單詞,將其存盤并將其提供給該函式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/496567.html
上一篇:了解指向c中指標的指標
下一篇:C參考傳遞
