第一个程序是第一章中的例子,第一次使用vim和gcc,花了好长时间才调试好,写完后一直放着没有整理。这里把一些零碎的东西整理一下。
这个程序的目的是从标准输入读取文本并对其进行修改,然后把它显示到标准输出。首先读取一行串列标号,这些列标号成对出现,表示输入行的列范围。这串列标号以一个负值结尾。剩余的输入行被程序读入并打印,然后输入行被选中范围的字符串被提取出来并打印。注意,每行第1列的列标号为0:
下面是程序的执行示例:
最后一行是在命令行下输入的EOF,此时会退出程序。
下面是程序的代码:注释写的很详细了,就不解释了。
/*这个程序从标准输入中读取输入行并在标准输出中打印这些输出行,
* 每个输入行的后面一行是该行内容的一部分。
*
* 输入的第一行是一串列标号,串的最后以一个负数结尾
* 这些列标号成对出现,说明需要打印的输入行的列范围。
* 例如:0 3 10 12 -1 表示第0列到第3列,第10列到第12列的内容将被打印*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_COLS 20 /*所能处理的最大列号*/
#define MAX_INPUT 1000 /*每个输入行的最大长度*/
int read_column_number(int columns[],int max);
void rearrange(char * output,char const *input,int n_columns,int const columns[]);
int main(){
int n_columns;/*进行处理的列标号*/
int columns[MAX_COLS];/*需要处理的列数*/
char input[MAX_INPUT];/*容纳输入行的数组*/
char output[MAX_INPUT];/*容纳输出行的数组*/
/*读取该串列标号*/
n_columns=read_column_number(columns,MAX_COLS);
/*读取,处理,打印剩余的输入行*/
while(gets(input)!=NULL){
printf("Original input: %s\n",input);
rearrange(output,input,n_columns,columns);
printf("Rearranged line: %s\n",output);
}
return EXIT_SUCCESS;
}
/*读取列标号,如果超出范围则不予理会*/
int read_column_number(int columns[],int max){
int num=0;
int ch;
/*读取列标号,如果所读取的数小于0则停止*/
while(num<max&&scanf("%d",&columns[num])==1&&columns[num]>=0)
num+=1;
/*确认已经读取的标号为偶数个,因为它们是以成对的形式出现的*/
if(num%2!=0){
puts("Last column number is not paired.");
exit(EXIT_FAILURE);
}
/*丢弃该行中包含最后一个数字的那部分内容*/
while((ch=getchar())!=EOF&&ch!='\n')
;
return num;
}
/*处理输入行,将指定列的字符连接在一起,输出行以NUL结尾*/
void rearrange(char * output,char const *input,int n_columns,int const columns[]){
int col;/*columns数组的下标*/
int output_col;/*输出列计数器*/
int len;/*输入行的长度*/
len=strlen(input);
output_col=0;
/*处理每对列标号*/
for(col=0;col<n_columns;col+=2){
int nchars=columns[col+1]-columns[col]+1;
/*如果输入行结束或输出行数组已满,就结束任务*/
if(columns[col]>=len||output_col==MAX_INPUT-1)
break;
/*如果输入行数据空间不够,只复制可以容纳的数据*/
if(output_col+nchars>MAX_INPUT-1)
nchars=MAX_INPUT-output_col-1;
/*复制相关数据*/
strncpy(output+output_col,input+columns[col],nchars);
output_col+=nchars;
}
output[output_col]='\0';
}
主要是一个标准库函数:gets,puts,scanf,getchar,strlen,strncpy的用法,这些函数可以参考c的文档说明。
这里我测试了一下gets函数,
#include <stdio.h>
#include <stdlib.h>
int main(){
char input[20];
while((gets(input)!=NULL)){
int len=strlen(input);
printf("len output:%d \n",len);
for(int i=0;i<len;i++)
{
printf("%c\n",input[i]);
}
printf("20 output:\n");
for(int i=0;i<20;i++){
printf("%c,%d\n",input[i],input[i]);
}
}
}
输入abcde,下面是输出结果:可以发现输入abcde时,gets函数往数组input中依次存储了'a','b','c','d','e'和'\0'这几个字符,使用strlen(input)返回5就很好理解了。使用这个方法可以测试其它函数的一些细节问题。
下面是gets函数的功能说明:从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为‘\0’空字符,并由此来结束字符串。