我已经在C字符串数组中读了几行文本。这些行有任意数量的制表符或空格分隔的列,我试图弄清楚如何删除它们之间的所有额外空格。最终目标是使用strtok来分解列。这是列的一个很好的例子:
Cartwright Wendy 93 Williamson Mark 81 Thompson Mark 100 Anderson John 76 Turner Dennis 56
如何消除列之间的所有空格或制表符,以便输出看起来像这样?
Cartwright Wendy 93
或者,我可以用不同的字符替换列之间的所有空格以便使用strtok吗?像这样的东西?
Cartwright#Wendy#93
编辑:多个很棒的答案,但必须选择一个。感谢所有人的帮助。
答案 0 :(得分:11)
如果我可以发出“你做错了”的意见,为什么不在阅读时消除空白呢?使用fscanf("%s", string);
读取“单词”(非空格),然后读取空格。如果是空格或制表符,请继续阅读一行“数据”。如果是换行符,请启动新条目。在C语言中,最简单的方法是将数据转换为可以尽快使用的格式,而不是尝试进行繁重的文本操作。
答案 1 :(得分:5)
为什么不直接使用strtok()
?无需修改输入
您需要做的就是重复strtok()
,直到获得3个非太空令牌然后就完成了!
答案 2 :(得分:2)
编辑:我最初有一个malloced工作区,我可能会更清楚。但是,没有额外内存这样做几乎一样简单,而且我在评论和个人即时通讯中被推,所以,这里来了......: - )
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;
}
答案 3 :(得分:2)
以下代码修改了字符串;如果您不想销毁原始输入,可以传递第二个缓冲区以接收修改后的字符串。应该是相当不言自明的:
#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;
}
答案 4 :(得分:1)
char* trimwhitespace(char *str_base) {
char* buffer = str_base;
while((buffer = strchr(str_base, ' '))) {
strcpy(buffer, buffer+1);
}
return str_base;
}
答案 5 :(得分:0)
您可以读取一行然后扫描它以找到每列的开头。然后使用您想要的列数据。
#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);
}
注意,代码仍然可以使用一些robust -ification:检查文件错误w / ferror;确保eof被击中;确保处理完整记录(所有列数据)。通过使用链表而不是固定数组也可以使其更加灵活,并且可以修改为不假设每列只包含一个单词(只要列由特定字符分隔)。
答案 6 :(得分:0)
这是一个替代函数,用于挤出isspace()
中<ctype.h>
定义的重复空格字符。它返回'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);
}
答案 7 :(得分:0)
我对John Bode的改进做了一些改进,以删除尾随的空格:
#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;
}
宽单峰
答案 8 :(得分:0)
下面的代码只是简单地输入字符,然后检查每个字符是否有空格多次跳过它,否则它会打印字符。 您也可以使用相同的逻辑选项卡。 希望它有助于解决您的问题。如果此代码有任何问题,请告诉我。
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 );
}
}
}