0

For my program, the goal is to read a string and use the input toward my code. However, we must note how some of my commands require only one input and some require two. For example: the "ina", "inb", "del", "rep" commands require 2 inputs, where as prn requires only 1. Is there another way I can apply this to my code, other than the way I have been using (scanf twice). Because when I want to use prn, I have to include an unnecessary int.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct node {
  int data;
  char *item;
  struct node* next;
};

//Global Variables
struct node* root = NULL;

//Prototypes
void ina();
void inb();
int length();
void prn();
void del();
void rep();

//Main
void main () {
  char command[4];
  int num;
  char str[255];


  while(1) {
    printf("Command? ");
    fflush(stdout);
    scanf("%s", &command); //This is where I want to generalize
    scanf("%d", &num);     //and clean up


      //Reads input and selects which command to execute
    if (strcmp(command, "ina")==0) {
      ina(num);
    } else
    if(strcmp(command, "inb")==0) {
      inb(num);
    } else
    if (strcmp(command, "prn")==0) {
      prn();
    } else
    if (strcmp(command, "del")==0) {
      del(num);
    } else
    if (strcmp(command, "rep")==0) {
      rep(num);
    } else
    if (strcmp(command, "end")==0) {
      exit(1);
    }
    else {
      return;
    }
  }

}




//Command Insert After
void ina(int n) {
  struct node* temp;
  temp = (struct node*)malloc(sizeof(struct node));

  temp->data = n;
  temp->next = NULL;

  if(root==NULL) {
    root = temp;
    printf("Text inserted at beginning\n");

  }
  else {
    struct node* p;
    p = root;

    while(p->next != NULL) {
      p = p->next;
    }
    p->next = temp;
      printf("Ok\n");

  }
}


//Command Insert Before
void inb(int n) {
  struct node* temp;
  temp = (struct node*)malloc(sizeof(struct node));
  temp->data = n;
  temp->next=NULL;

  if (root == NULL) {
    root = temp;
    printf("Text inserted at beginning\n");
    fflush(stdout);
  }
  else {
    temp->next=root;
    root = temp;
    printf("Ok\n");
    fflush(stdout) ;
  }

}

//Command Length, not necessary but use for delete command
int length() {
  struct node* temp;
  int count = 0;
  temp = root;

  while(temp != NULL) {
    count++;
    temp = temp->next;
  }
  return count;
}

//Command Print
void prn() {
  struct node* temp;
  temp = root;

  if(temp == NULL) {
    printf("List is empty\n");
    fflush(stdout);
  }
  else {
    while(temp != NULL) {
      printf("%d\n",temp->data);
      temp = temp->next;
    }
    printf("\n");
  }
}

//Command Delete
void del(int n) {
  struct node* temp;

  if(n > length()) {
    printf("No Such Index\n");
    fflush(stdout);
    return;
  }
  else if(n==1) {
    temp = root;
    root = temp->next;
    temp->next = NULL;
    free(temp);
  }
  else {
    struct node* p = root, *q;
    int i = 1;
    while(i<n-1) {
      p = p->next;
      i++;
    }
    q = p->next;
    p->next = q->next;
    q->next = NULL;
    free(q);
  }
    printf("Deleted\n");
    fflush(stdout);
}

//Command Replace FIX
void rep(int i) { 
  int old, n;
  struct node* temp;
  temp = root;
  old = i;

  printf("\nEnter what you want to replace with: ");
  scanf("%d", &n);

  if(temp == NULL) {
    printf("No such index\n");
    return NULL;
}
  while (temp != NULL) {
  if(temp->data == old) {
    temp->data = n;
      printf("Replaced\n");

  }
  temp = temp->next;
}
}

Output Notice how "prn" command I had to add an unnecessary 1 and for the "end" command I didn't add anything at first and nothing processed. Output image

Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • If I understand you correctly, only part of the functions will require an argument and require you to take additional input. Am I correct ? – Tony Tannous Nov 04 '17 at 22:47
  • Yes, sorry if it was unclear. But the input is all supposed to be read in one line. –  Nov 04 '17 at 22:48
  • Can you provide an example of input ? – Tony Tannous Nov 04 '17 at 22:49
  • @TonyTannous I just added an output image and a little description on my problem. –  Nov 04 '17 at 22:52
  • If the input consist of one line, then save it in an array, then parse that array reading the function name, then turn the second part after the space to an integer to be sent as the parameter. I guess you know how to turn a string to an int. `123` just multiply 3 by 1, add 2 multiplied by 10, and 3 multiplied by 100 and so on for every number. – Tony Tannous Nov 04 '17 at 22:53
  • It's unclear what you asking. – Raindrop7 Nov 04 '17 at 22:54
  • @Raindrop7 it is very clear to me. Input is a string which contains both function and a parameter. Problem occurs when there's no parameter as function takes non and the second scanf stops the program waiting for input. – Tony Tannous Nov 04 '17 at 22:56
  • `scanf("%s", &command)` is a type error. `%s` takes `char *`, not `char (*)[4]`. – melpomene Nov 04 '17 at 22:57
  • Read the whole input into an array with the space as well. Then parse that input. – Tony Tannous Nov 04 '17 at 22:57
  • @TonyTannous: But the OP all the functions' prototypes take `void` while he/she's passing `int` to `rep`?! – Raindrop7 Nov 04 '17 at 22:59
  • This is at least the 5th time today this question has been asked in various forms. The asker keeps deleting the question after getting the answer https://stackoverflow.com/questions/47115119 – Barmak Shemirani Nov 04 '17 at 23:42

2 Answers2

2

To give an idea away, if not the code.

Break the input line into an argv[] type list (don't forget the NULL pointer at the end). Then you can pass the entire list to each of your functions using xxx(argc, &argv) letting them call getopt() to parse their own arguments. They can now handle any number of arguments (artc=1 for no argument, just command name) on up to a YOUR_ARG_MAX value.

You could use strtok_r() on white space delimiters " \t\r\n" or strtok() if you don't have the the reentrant version. As strtok operations put a \0 after each token you just need to save the token addresses in a char *argv[1+YOUR_ARG_MAX] array with a NULL termination counting arguments in an argc variable.

Gilbert
  • 3,740
  • 17
  • 19
1

You can after inputting command check its value so if it is one of the functions which take one parameter then issue the second scanf otherwise call only the functions which take 0 parameters:

scanf("%s", &command); //This is where I want to generalize

if (strcmp(command, "ina") == 0){
    scanf("%d", &num);
    ina(num);
}
else
    if(strcmp(command, "inb" ) == 0){
      scanf("%d", &num);
      inb(num);
    }
else
    if (strcmp(command, "prn") == 0)
      prn();
else
    if (strcmp(command, "del") == 0){
        scanf("%d", &num);
        del(num);
} 
else
    if (strcmp(command, "rep")==0)
        scanf("%d", &num);
        rep(num);
} 
else
if (strcmp(command, "end") == 0) {
  exit(1);
  • Also note that the code doesn't compile: You declared: ina, inb, del, rep as functions taking 0 parameter but when invoking them you pass an integer: rep(num)... So declare them correctly.
Raindrop7
  • 3,889
  • 3
  • 16
  • 27