0

/*

I am trying to program a Tideman alternative method algorithm.
I am taking i/p through command-line-argument.
When I try to print the populated candidate array.
It is printing single characters when format specifier is char type. The result of other specifier is attached.
When format specifier is string When format specifier is integer When format specifier is character */

/*

Same logic when executed on CS50 IDE, it prints the strings as expected.
I mean if the CLA is Alice Bob Charlie, then at 0th index Alice and so on...
This step is crucial as later the names from the voters would be compared.
I don't how to proceed from here. I came to know only about this when I reached the comparison stage. */

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

#define MAX 9

int preferences[MAX][MAX]; 


bool locked[MAX][MAX];

typedef struct
{
    int winner;
    int loser;
}
pair;

char candidates [MAX] = {0};
pair pairs[MAX*(MAX-1)/2];


int pair_count = MAX;
int candidate_count = MAX;

//Prototypes
bool vote (int rank, char name, int ranks[]);
void record_preferences(int ranks[]);
void add_pairs();
void sort_pairs();
void lock_pairs();
void print_winner ();

int main(int argc, char *argv[])
{

//Check for invalid usage.  
    if (argc < 4)
    {
        printf("Usage: tideman [candidate ...]\n");
        return 1;
    }

    candidate_count = argc - 1;
    if (candidate_count > MAX)
    {
        printf("Maximum number of candidates is %i\n", MAX);
        return 2;
    }
//popuplate the candidate array.  
    for (int i = 0; i < candidate_count; i++)
    {
        candidates[i] = argv[i+1];
        printf("Candidate array: %c\n", *argv[i+1]);
    }
}
M K Sundaram
  • 49
  • 1
  • 7
  • You don't print the `candidates` array anywhere. You only print the first characters of `argv[i+1]`. How do you call the program (that's cut away on your screenshots) and what do you want to have in the `candidates` array? – mch Jan 12 '21 at 10:15
  • If you require `argc > 3`, then your usage statement should be `tideman candidate candidate candidate [ candidate ...]`. If you print a usage statement instead of an error message (that is, if you want to consider too few candidates to be a valid request for a usage statement rather than an error), you should `return EXIT_SUCCESS`. If you want to consider it an error, you should print an error message to stderr and return EXIT_FAILURE. – William Pursell Jan 12 '21 at 10:22
  • I do not understand what your question is, but perhaps you are simply looking for `printf("Candidate array: %s\n", argv[i + 1]);` – William Pursell Jan 12 '21 at 10:25
  • @WilliamPursell I expect candidate array should have Alice in 0th index and Bob in index 1 and Charlie in index 2. – M K Sundaram Jan 12 '21 at 10:59
  • So perhaps you just want `argv += 1` or `char **array = argv + 1; printf("Candidate array: %s\n", array[i]);` – William Pursell Jan 12 '21 at 11:04
  • 1
    Please do not add pictures of plain text. Instead you can copy&paste the code and messages as plain text into the question. – Gerhardh Jan 12 '21 at 11:36
  • @WilliamPursell I want to see whether I the array consist of strings or not. So that later I can compare with other input to return as true or false. – M K Sundaram Jan 12 '21 at 11:36
  • @Gerhardh I thought images make thing more clear and easy to understand. In case I failed to make a point through words. anyway, I would keep your suggestion in mind. – M K Sundaram Jan 12 '21 at 11:39
  • 1
    If you copy&paste the same text as plain text instead you get exactly the same information. Also code from images cannot be copied or searched. If one wants to cite and fix the erronous code, they need to retype everything instead of c&p. – Gerhardh Jan 12 '21 at 11:45
  • The elements of `argv` are strings. Do you mean you want to validate that they only contain certain characters? (eg, every element of the string is alphabetic) – William Pursell Jan 12 '21 at 16:59

2 Answers2

1

Your problem is understanding how arguments work. Consider this line in the terminal: ./main tideman abc How does argv looks like? It is an array.. with 3 elements in it:

argv[0] => "main"
argv[1] => "tideman"
argv[2] => "abc"

Lets say instead of abc you have ./main tideman a b c. How does argv looks like? It is an array.. with 5 elements in it:

argv[0] => "main"
argv[1] => "tideman"
argv[2] => "a"
argv[3] => "b"
argv[4] => "c"

candidates is a char array, so it can hold characters. Now lets consider first example (./main tideman abc). What is the for-loop in your code does? candidates[0] = argv[1]. What is wrong here? candidates[0] is the first character in the candidates array.. Cool. argv[1] is "tideman".. a string. I hope you can see the assignment problem here.

Now the second problem, in the second part of the loop. With the first iteration, argv[0+1] is "tideman" Now you want to print the string tideman to the screen. The command print("%s\n") does print a string, and it take as argument pointer to that string. What is the pointer? its argv[1].. which is a pointer to the first element in the argv[1] array. What is *argv[1]? Thats right, its the value of the first character in the argv[1] array.. So in our example argv[1] is "tideman", so *argv[1] is 116 which is the ascii value for t.

So in order to achieve your goal of printing "tideman", which is argv[1] you just need printf("%s\n", argv[1]); with argument argv[1] you supply pointer to the first character of the string, which is what %s ask for.

So to recap you have 2 problems in your for-loop, and you could see both of those problem as warnings in the terminal.

Gal Birka
  • 581
  • 6
  • 16
1

In C language, a char is a single character. A string is by convention a null terminated character array. For that reason, it is common to use char * to represent strings. And it is up to the programmer to make sure that the life time of the pointed array does not end before the value is used.

Warnings are to be observed. Unless you know what a warning means and why you want to ignore it, you really should treat them as errors.

Here the information was in the first warning you have shown:

    candidates[i] = argv[i + 1];

... warning: assignment to char from char *...

It means that argv[i+1] does represent a string, but you try to assign it into a single char which invokes Undefined Behaviour.

Here is a quick fix for your current code:

...
char *candidates [MAX] = {NULL};  // candidates is an array of strings
...
    //popuplate the candidate array.  
    for (int i = 0; i < candidate_count; i++)
    {
        candidates[i] = argv[i + 1];
        printf("Candidate array: %s\n", argv[i + 1]);    // use %s in C to display a string
    }
...
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • This quick fix fixed my issue. You are right that I couldn't interpret the errors. If you don't mind could you please tell me what this sentence means which is extracted from your post. ( And it is up to the programmer to make sure that the lifetime of the pointed array does not end before the value is used.) Thanks – M K Sundaram Jan 12 '21 at 11:08
  • Particularly the lifetime of the pointed array doesn't end... Sorry forgot to mention this in the previous post. – M K Sundaram Jan 12 '21 at 11:32
  • 1
    @MKSundaram C is not a beginner friendly language, because there are tons of pitfalls: a syntactically correct code can easily produce a crash at run time of even worse invoke Undefined Behaviour. For the *life-time* of an object, you can read this other [post](https://stackoverflow.com/a/13132808/3545273). And the [C tag page](https://stackoverflow.com/tags/c/info) contains other pointers to intesting posts about various C language caveats in its FAQ part. Happy learning :-) – Serge Ballesta Jan 13 '21 at 08:05