Пользовательский ввод, представляющий собой команду и имя файла, позволяет создать имя файла и сохранить содержимое linkedlist

#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)); работать?