#c #file #pointers #printing
#c #файл #указатели #печать
Вопрос:
Программа knapsack, которую я пытаюсь создать, имеет пользовательский интерфейс, который принимает команды, одна из них — сохранить и загрузить из файла. Мне интересно, как вы создаете файл на основе пользовательского ввода, когда эта команда задается в одной строке, а затем сохраняете содержимое связанного списка в этот файл, а затем можете загрузить его и распечатать позже. Часть того, что меня сбивает с толку, — это получение всего этого в одном вводе, а затем печать содержимого в это пользовательское имя файла. Как это можно сделать, должен ли я использовать fopen и fprintf? Также, если заданное имя файла является чем-то вроде /rootfile, тогда оно должно быть помечено как невозможное сохранить в этот файл, поскольку это каталог. Они также должны быть двоичными файлами.
knapsack-shell.c
#include <stdio.h>
#include "knapsack.c"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void removeSpaces(char *str1)
{
char *str2;
str2=str1;
while (*str2==' ') str2 ;
if (str2!=str1) memmove(str1,str2,strlen(str2) 1);
}
int main()
{
listitemptr k2 = NULL;
char input[100];
char command;
int i, returnval = 0;
char filename[250];
char userfile[260];
char *error;
for (;;) {
FILE* pf = NULL;
fprintf(stdout, "> ");
if (!fgets(input, sizeof input, stdin))
break;
i = strspn(input, " tn"); /* skip blanks */
command = input[i ];
if (command == 'q' amp;amp; input[i] == 'n')
break;
if (command == 'p') {
KnapsackPrint(amp;k2);
continue;
}
if (command == 'a') {
int item;
if (sscanf(input i, "%i", amp;item) != 1) {
error = input i;
removeSpaces(error);
fprintf(stderr, "Error: Bad item "%s"n", strtok(input i, "n"));
continue;
}
KnapsackAdd(amp;k2, item);
KnapsackPrint(amp;k2);
continue;
}
if (command == 'r') {
int item;
if (sscanf(input i, "%i", amp;item) != 1) {
error = input i;
removeSpaces(error);
fprintf(stderr, "Error: Bad item "%s"n", strtok(input i, "n"));
continue;
}
if(KnapsackRemove(amp;k2, item) == -1){
fprintf(stderr, "Error: item %d does not exist in knapsackn", item);
continue;
}else{
KnapsackPrint(amp;k2);
continue;
}
}
if(command == 's'){
if(( pf = fopen(input i, "a")) != NULL){
error = input i;
removeSpaces(error);
fprintf(pf, "%s", KnapsackPrint2(amp;k2));
fprintf(stdout, "stored in file "%s"n", strtok(input i, "n"));
}
continue;
}
if(command == 'l'){
continue;
}
else{
fprintf(stderr, "unknown command: %s", input);
fprintf(stdout, "> ");
}
}
return returnval;
}
knapsack.c
#include "knapsack.h"
#include <stdio.h>
#include <stdlib.h>
listitemptr KnapsackAdd(listitemptr *knapsack, int item){
if(*knapsack==NULL){//empty list
listitemptr newest= malloc(sizeof(struct listitem));
newest->item=item;
newest->count=1;
newest->next=NULL;
*knapsack = newest;
return newest;
}else{
listitemptr current=*knapsack;
listitemptr prev=NULL;
while(current!=NULL){
if(current->item == item){
current->count=current->count 1;
break;
}else if(current -> item > item){
listitemptr new_node = malloc(sizeof(struct listitem));
new_node-> item = item;
new_node-> count= 1;
new_node-> next = current;
if(prev != NULL ){
prev->next = new_node;
}else {
*knapsack = new_node;
}
break;
}
prev=current;
current=current->next;
}
if(current==NULL){
listitemptr newest= malloc(sizeof(struct listitem));
newest->item=item;
newest->count=1;
newest->next=NULL;
prev->next=newest;
return newest;
}
return current;
}
}
int KnapsackRemove(listitemptr *knapsack, int item){
if(*knapsack==NULL)
return -1;
listitemptr present=*knapsack;
listitemptr previous=NULL;
while(present!=NULL){
if(present->item==item){
if(present->count>1){
present->count=present->count-1;
}else{
if(previous==NULL){ //delete at head
*knapsack=present->next;
}else{
previous->next=present->next;
free(present);
}
}
break;
}
previous=present;
present=present->next;
}
return 0;
}
void KnapsackPrint(const listitemptr *knapsack){
if(*knapsack==NULL)
printf("knapsack: n");
else{
listitemptr temp=*knapsack;
printf("knapsack:");
while(temp!=NULL){
if((temp->next) == NULL){
printf(" %d (%d)", temp->item, temp->count);
break;
}else{
printf(" %d (%d),",temp->item,temp->count);
temp=temp->next;
}
}
printf("n");
}
}
unsigned int KnapsackItemCount(const listitemptr *knapsack, int item){
if(*knapsack==NULL)
return 0;
listitemptr temp=*knapsack;
while(temp!=NULL){
if(temp->item==item)
return temp->count;
temp=temp->next;
}
return 0;
}
unsigned int KnapsackSize(const listitemptr *knapsack){
if(*knapsack==NULL){
return 0;
}
listitemptr temp=*knapsack;
unsigned int sum=0;
while(temp!=NULL){
sum =temp->count;
temp=temp->next;
}
return sum;
}
listitemptr KnapsackPrint2(const listitemptr *knapsack){
if(*knapsack==NULL)
printf("knapsack: n");
else{
listitemptr temp=*knapsack;
printf("knapsack:");
while(temp!=NULL){
if((temp->next) == NULL){
printf(" %d (%d)", temp->item, temp->count);
break;
}else{
printf(" %d (%d),",temp->item,temp->count);
temp=temp->next;
}
}
printf("n");
return temp;
}
}
Комментарии:
1. Не беспокойтесь о явной проверке того, является ли файл каталогом. в таком случае
fopen
произойдет сбой, поэтомуif( (file = fopen(path, mode)) == NULL ) { perror(path); ... }
этого достаточно.2. о, это потрясающе, я не знал, что у fopen есть такая возможность. Как бы я мог получить имя файла от пользователя, а затем распечатать содержимое в указанный файл с помощью fopen? я бы перевел это в режим ‘w’, верно? KnapsackPrint корректно печатает содержимое файла, но сохранить его вывод в файл явно невозможно, не так ли?
3. Вам нужно решить, как вы хотите сохранить содержимое. То есть вам нужно сериализовать данные (json, avro, protobuf, … или создать свою собственную сериализацию). Поскольку вы игнорируете пробелы в данных, вы, вероятно, можете сохранить список по одной записи в строке (например, вы определяете свой собственный метод сериализации). Да,
fprintf
вероятно, это хороший способ.4. Но, возможно, проблема, с которой вы столкнулись, заключается в том, что ваша попытка сохранить данные обрезает данные, уже имеющиеся в файле. Возможно, вы захотите, чтобы mode
"a"
добавлял данные при их записи, а не отбрасывал содержимое, уже имеющееся в файле.5. может ли что-то вроде
fprintf(filename, "%s", KnapsackPrint(amp;k2));
работать?