Remove extra space inside line C?

I read a few lines of text into an array of C-lines. Lines have an arbitrary number of columns or delimiters, separated by spaces, and I'm trying to figure out how to remove all the extra spaces between them. The ultimate goal is to use strtok to split the columns. This is a good example of columns:

  Cartwright Wendy 93
 Williamson Mark 81
 Thompson mark 100
 Anderson john 76
 Turner Dennis 56 

How can I remove all spaces or tabs between columns so that the result looks like this?

 Cartwright Wendy 93 

Alternatively, is it possible to simply replace all spaces between columns with another character to use strtok? Something like that?

  Cartwright # Wendy # 93

edit: Some excellent answers, but you had to choose one. Thanks for the help.

+4
source share
9 answers

If I can voice the opinion "you are doing it wrong," why not just fill in the gaps while reading? Use fscanf("%s", string); to read the β€œword” (without spaces), then read the spaces. If these are spaces or tabs, continue reading in one β€œline” of data. If this is a new line, start a new entry. Most likely, it is easiest in C to get data in a format that you can work with as soon as possible, instead of trying to manipulate text messages in harsh conditions.

+11
source

Why not use strtok() directly? No need to change input

All you have to do is repeat strtok() until you get 3 non-indirect tokens and then you are done!

+5
source

Change Initially, I had a malloced workspace, which I could be more clear. However, doing it without additional memory is almost as easy, and they push me this way in the comments and personal chats, so here ... :-)

 void squeezespaces(char* row, char separator) { char *current = row; int spacing = 0; int i; for(i=0; row[i]; ++i) { if(row[i]==' ') { if (!spacing) { /* start of a run of spaces -> separator */ *current++ = separator spacing = 1; } } else { *current++ = row[i]; spacing = 0; } *current = 0; } 
+2
source

The following code changes the line in place; if you do not want to destroy the original input, you can pass a second buffer to get the modified string. It should be clear enough:

 #include <stdio.h> #include <string.h> char *squeeze(char *str) { int r; /* next character to be read */ int w; /* next character to be written */ r=w=0; while (str[r]) { if (isspace(str[r]) || iscntrl(str[r])) { if (w > 0 && !isspace(str[w-1])) str[w++] = ' '; } else str[w++] = str[r]; r++; } str[w] = 0; return str; } int main(void) { char test[] = "\t\nThis\nis\ta\b test."; printf("test = %s\n", test); printf("squeeze(test) = %s\n", squeeze(test)); return 0; } 
+2
source
 char* trimwhitespace(char *str_base) { char* buffer = str_base; while((buffer = strchr(str_base, ' '))) { strcpy(buffer, buffer+1); } return str_base; } 
+1
source

You can read a row, then scan it to find the beginning of each column. Then use the column data, but you want to.

 #include <stdio.h> #include <string.h> #include <ctype.h> #define MAX_COL 3 #define MAX_REC 512 int main (void) { FILE *input; char record[MAX_REC + 1]; char *scan; const char *recEnd; char *columns[MAX_COL] = { 0 }; int colCnt; input = fopen("input.txt", "r"); while (fgets(record, sizeof(record), input) != NULL) { memset(columns, 0, sizeof(columns)); // reset column start pointers scan = record; recEnd = record + strlen(record); for (colCnt = 0; colCnt < MAX_COL; colCnt++ ) { while (scan < recEnd && isspace(*scan)) { scan++; } // bypass whitespace if (scan == recEnd) { break; } columns[colCnt] = scan; // save column start while (scan < recEnd && !isspace(*scan)) { scan++; } // bypass column word *scan++ = '\0'; } if (colCnt > 0) { printf("%s", columns[0]); for (int i = 1; i < colCnt; i++) { printf("#%s", columns[i]); } printf("\n"); } } fclose(input); } 

Please note that the code can still use some reliable identification: check for w / ferror file errors; ensure that eof is hit; provide a complete record (all column data). It can also be made more flexible by using a linked list instead of a fixed array and can be modified so as not to assume that each column contains only one word (provided that the columns are separated by a specific character).

0
source

Here's an alternate function that extrudes repeated whitespace as defined by isspace() in <ctype.h> . It returns the length of the string "squidged".

 #include <ctype.h> size_t squidge(char *str) { char *dst = str; char *src = str; char c; while ((c = *src++) != '\0') { if (isspace(c)) { *dst++ = ' '; while ((c = *src++) != '\0' && isspace(c)) ; if (c == '\0') break; } *dst++ = c; } *dst = '\0'; return(dst - str); } #include <stdio.h> #include <string.h> int main(void) { char buffer[256]; while (fgets(buffer, sizeof(buffer), stdin) != 0) { size_t len = strlen(buffer); if (len > 0) buffer[--len] = '\0'; printf("Before: %zd <<%s>>\n", len, buffer); len = squidge(buffer); printf("After: %zd <<%s>>\n", len, buffer); } return(0); } 
0
source

I made a slight improvement over John Bode to remove trailing spaces:

 #include <ctype.h> char *squeeze(char *str) { char* r; /* next character to be read */ char* w; /* next character to be written */ char c; int sp, sp_old = 0; r=w=str; do { c=*r; sp = isspace(c); if (!sp) { if (sp_old && c) { // don't add a space at end of string *w++ = ' '; } *w++ = c; } if (str < w) { // don't add space at start of line sp_old = sp; } r++; } while (c); return str; } #include <stdio.h> int main(void) { char test[] = "\t\nThis\nis\ta\f test.\n\t\n"; //printf("test = %s\n", test); printf("squeeze(test) = '%s'\n", squeeze(test)); return 0; } 

w.

0
source

The following code just takes the input character wise and then checks each character if there is a space more than once when it skips it, otherwise it prints the character. The same logic can be used for the tab. Hope this helps solve your problem. If there is any problem with this code, please let me know.

  int c, count = 0; printf ("Please enter your sentence\n"); while ( ( c = getchar() ) != EOF ) { if ( c != ' ' ) { putchar ( c ); count = 0; } else { count ++; if ( count > 1 ) ; /* Empty if body */ else putchar ( c ); } } } 
0
source

All Articles