【发布时间】:2021-03-14 13:01:17
【问题描述】:
我正在开发一个程序,该程序从脚本获取输出,存储它并以某种方式打印输出,更具体地说是:(名字,中间名/姓氏,键)或(中间名/姓氏,第一名称,密钥)等...
所以我编写了程序,但是当我尝试运行它时,我不断收到分段失败。 编译很好,脚本可以工作,因为我测试过。
有什么可以做的不同或改进的建议吗?
代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
struct memberinfo {
char firstname[250]; // all names except last name
char surname [100]; // surname
int pub_key; // 0 if the user does not have a key
};
typedef struct memberinfo acc_t;
int counter = 0;
void les_data (acc_t *classlist);
void skriv_data (acc_t *classlist, char * select);
int main(int argc, char *argv[]) {
acc_t classlist[200];
char *ch = NULL;
if(argc == 2){//checking for additional argument on execute
ch = argv[1];//pointer becomes main argument
}
else if(argc < 2){//if there is less then 2 arguments
ch = getenv("V1");//pointer gets the default environmental variable.
}
else{//same as above, this just makes sure that "ch" don't return with NULL value
argc == 1;
ch = getenv("V1");
}
read_data (classlist);//calling the method for executing the script and store output
print_data(classlist, ch);//calling the method for printing the data
return 0;
}
void read_data(acc_t *classlist) {
FILE * list;
char *name, *fname, *lname, *tmp;
char usertmp[1000], buffer[BUFSIZ+1];//usertmp = temporary list, buffer contain the scripts output
int cnt, i, chars_read;
memset(buffer, '\0', sizeof(buffer));//memsetting buffer with all 0
list = popen("./classlist.sh", "r");//opening and running the script in a read mode
while(list!=NULL){ //if list is not NULL, we begin to read from it
chars_read = fread(buffer, sizeof(char), BUFSIZ, list);//reading from scripts output,
//storing in buffer.
while(chars_read >0){
//while there are still characters in file we do:
tmp = buffer;//setting pointer to the text stored in buffer
for(i = 0; tmp[i]!= '\n'; i++){//for-loop running until a new line is detected
if(tmp[i]== ' '){ //if there is a space in text the counter increases
cnt++;
}//if end
}//for-loop end
name = strtok(buffer,": ");//the complete name is taken from the text in buffer
strcpy(usertmp, name);//the name is copied to usertmp array
for(i = 0; i <(cnt-2); i++){//for-loop
name = strtok(NULL, ": ");
strcat(strcat(usertmp, " "), name); //nested strcat??
}//for-loop end // saves the whole name in usertmp[]
name = NULL;//setting name to null, clearing the memmory
strcpy(classlist[counter].firstname, name);//copying first name in array
name = strtok(NULL, ": ");//setting to NULL to skip first name
strcpy(classlist[counter].surname, usertmp);//copy middle/last name
name = strtok(NULL, ": ");//setting to null to skipp the middle/last name
classlist[counter].pub_key = atoi(name);//copy the int key to array
counter ++;
}//if(chars_read) end
pclose(list);
}//while end
}//read_data end
void print_data (acc_t *classlist, char *select) {
switch (select[0])
{
case 'k':
printf("%s %s %d\n", classlist[counter].firstname, classlist[counter].surname,
classlist[counter].pub_key);
//printf("Printing out class data:\n");
break;
default:
break;
}
}
所以脚本会像这样打印一组成员:
脚本:
#! /bin/bash
grep da2001-2020 /etc/group |cut -f4 -d: > group.txt
#Getting a list of members
tr -s ',' '\n' < group.txt |sort -k 1 -t',' -n > snm.txt
#putting numbers in a order
sed 's/^.//' snm.txt > cnm.txt
#removing "s" in front of student number.
rm group.txt #delting group file
cut -f1,5 -d: /etc/passwd |cut -f1 -d, |sort -u > big_list.txt
#extracting names from file
grep -f snm.txt big_list.txt > final.txt
#comparing the two lists
wc -l < final.txt > amount.txt
#counting students
for id in $(cat cnm.txt);
#scaning student numbers that were selected
do
File=$(curl -k --silent -q https://website.com/~$id/pub_key.asc| grep -o
"BEGIN PGP PUBLIC KEY BLOCK")
#curling a request for file indicator pub_key.asc
if [ "$File" ];
then
grep "$id" final.txt | cut -f2 -d: | sort > verification.txt
echo -e "$(cat verification.txt): 1 " #indicating has key
#placing the students who have a key in a file with indicator
else
grep "$id" final.txt | cut -f2 -d: | sort > verification.txt
echo -e "$(cat verification.txt): 0 " #indicator no key
#placing the students who dont have key in a file with indicator
fi
done 2>&1 | tee classlist.txt #exit loop, print and save output file
rm amount.txt
rm cnm.txt
rm big_list.txt
rm snm.txt
rm verification.txt
rm final.txt
【问题讨论】:
-
您对代码中的分段发生位置有任何猜测吗?
-
你应该为你的转发函数使用原型,或者把它们放在
main之前。另外:argc == 1;,你想在那里做什么? -
请启用/检查编译器警告。我收到 3 个警告,2 个错误。除了 David 提到的,您还需要使用原型声明函数
read_data()和print_data()。 -
...以及
read_data()中针对cnt++;未初始化变量 的另一个警告。 -
@ryyker 错误是针对没有原型的两个函数。首先每个都有一个警告,当函数本身被编译时,错误来自一个不匹配的定义(与编译器之前的假设相矛盾)。 MSVC:
popen()和pclose()也出现错误,但这是意料之中的。
标签: c linux subprocess popen strtok