在C中,如何删除char数组中相同且连续的行?
我正在寻找一些创建函数的帮助。
函数deleteIdents()将删除char数组中的相同行,因为它们是连续的。 它将保持相同的一条线。
我不需要检查整行是否相同。 只有前79个字符,MAXCHARS,适用于这种情况。
因此,例如,如果我的数组包含
Hello World Hi World Hello World Hello World Hello World Hi there
它将被改为
Hello World Hi World Hello World Hi there
在我的脑海中,该function看起来类似于:
int deleteIdents(char *a) { int i; for (i=0; i<=MAXCHARS; i++) { if (a[i] != '\n') /* copy into new array */ } } }
但我不确定。 如果你有一个解决方案,我会很高兴和感谢听到它:)
读取第一行比第二行,如果它们相等则比较它们进入循环直到它们不相等。 所以这是代码:
char *first_line = malloc(MAXLINE); char *second_line = malloc(MAXLINE); getline(first_line); do { getline(second_line); } while (strcmp (first_line, second_line));
对于getline()
实现搜索,有很多例子。 或者在这里你有我的。
如何实现它的另一个例子。 想法是保留2个指针,并且仅在条目不同时才增加第一个指针。 还分配了一些额外的存储空间以避免已被覆盖的条目的内存泄漏。
#include #include #include int unique(char **strings, int size) { if (!strings) { return -1; } int head = 0, newHead = 0, duplicatedElementsHead = 0; //Save duplicates to avoid memory leaks char** duplicatedEntries = malloc(size*sizeof(char*)); while (head < size) { //String are the same if (!strcmp(strings[head], strings[newHead])) { if (head != newHead) { duplicatedEntries[duplicatedElementsHead++] = strings[newHead]; } ++head; } else { strings[++newHead] = strings[head++]; } } //Put duplicated entries after new end int idx = 0, tmpHead = newHead + 1; for (; idx < duplicatedElementsHead; ++idx) { strings[tmpHead++] = duplicatedEntries[idx]; } free(duplicatedEntries); return newHead; } int main() { char **strings = malloc(8*sizeof(char*)); strings[0] = "Hello World"; strings[1] = "Hi World"; strings[2] = "Hi World"; strings[3] = "Hello World"; strings[4] = "Hello World"; strings[5] = "Hi there"; strings[6] = "Hia"; strings[7] = "Hi"; int newEnd = unique(strings, 8); for (int i=0; i < newEnd; ++i) { printf("%s\n", strings[i]); } free(strings); }
您实际上是在编写unix / linux实用程序’uniq’的核心function。
cat filename | sort | uniq > newfile #or skip sort, since you didn't mention cat filename | uniq > newfile
你可以使用popen和uniq(像这样……)
FILE *uniqfh; uniqfh = popen("cat file1 | uniq" , "r"); if (uniqfh == NULL) { //handle error } while( fgets(uniqfh, buffer, buffersize) ) printf("%s\n",buffer);
但说真的,你可以编写uniq()的核心,
static long MAXUNIQ=79; //or whatever you want char* isdup(char* prev, char* next, long len) { //if( !prev || !next) error long n = len<=0 ? MAXUNIQ : len; for( ; *prev==*next && n --> 0; ) { //down-to operator (sic) ; //clearly nothing happening here! } return( (n<1) || !(*p+*n) ); } /yeah, this is actually strncmp, but hey
你需要一个'字符串'数组(char *或char []),让我们读一下,
char* ray[ARRAYMAX]; //define how many elements of your arRay //could use, char** ray; and malloc(ARRAYMAX*sizeof(char*)) long read_array(FILE* fh, char* ray[]) { char buffer[MAXLINE+1]; long count=0; while( fgets(buffer,sizeof(buffer),fh) ) { //you could eat dups here, or in separate function below //if( (count<1) && !isdup(ray[count-1],buffer,MAXUNIQ) ) ray[count++] = strdup(buffer); } //ray[0] through ray[count-1] contain char* //count contains number of strings read return count; } long deleteIdents(long raysize, char* ray[]) //de-duplicate { long kept, ndx; for( ndx=1, kept=0; ndx
你需要这个来称呼它......
... long raysize; char* ray[ARRAYMAX] = {0}; //init to null pointers raysize = read_array(fopen(filename,"r"),ray); raysize = deleteIndents(raysize,ray); ...
之后,你需要释放malloc'ed字符串,
for( ; 0 <-- raysize; ) { free(ray[raysize]); ray[raysize] = NULL; }
以下程序在字符串元素数组上执行您所需的操作。 我们用两个指针导航数组,初始化为第一个和第二个元素。 我们运行一个array_n - 1
的循环array_n - 1
个元素与下一个元素的比较,比较两个字符串……如果它们不同,我们将*source_ptr
字符串指针复制到*target_ptr
位置。 如果它们不同,我们只增加source_ptr
,所以它指向下一个数组字符串,但不复制它 (这使我们有效地删除指针)我们也管理新数组(我们使用相同的数组作为源和目的地,因为我们只能删除数组元素,所以每次我们在两个指针之间有一个更大的漏洞)
pru.c
#include #include #include /* array of strings */ char *array[] = { "Hello World", "Hi World", "Hello World", "Hello World", "Hello World", "Hi there", }; size_t array_n = sizeof array / sizeof *array; int main() { int i; char **target_ptr = array, **source_ptr = array + 1; size_t new_length = 1; for (i = 1; i < array_n; i++) { /* if strings pointed to by pointers are equal */ if (strcmp(*target_ptr, *source_ptr) == 0) { /* go to the next, effectively discarding the second pointer */ source_ptr++; } else { /* copy both pointers in place, to the destination array */ *target_ptr++ = *source_ptr++; new_length++; /* increment array length */ } } /* finally, we have in the array only the good pointers */ /* print'em */ for (i = 0; i < new_length; i++) printf("%s\n", array[i]); exit(0); }
就这样。
样品运行:
$ pru Hi World Hello World Hi there Hello World $ _