Parse arguments into an array - c

I am trying to create a simplified version of the Rummy card game. I need to parse in the card abbreviations for example SA is Spades Ace. DT is Diamond 10 etc. I know there is an easier way to do this but that's how my assignment wants it done.
The sample execution would look like
rummy 3 S2 H9 C4... etc. include all 52 cards.
The number in argv[1] is the players in the game. How am I supposed to take the cards starting after the number and put them into an array?
My code so far
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int players = *argv[1];
char deck[52];
int i, j, pid, cid;
if (players > '5' || players < '3')
{
printf("%c is not the allowed number of players, min is 3 and max is 5\n",*argv[1]);
exit(0);
}
}

Quick and dirty demonstration:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int players = atoi(argv[1]);
char deck[52][3];
int i, j, pid, cid;
if (players > 5 || players < 3)
{
printf("%d is not the allowed number of players, min is 3 and max is 5\n", players);
exit(0);
}
for (i = 0; i < argc - 2; i++)
{
strcpy(deck[i], argv[i+2]);
}
for (i = 0; i < argc - 2; i++)
{
printf("%s\n", deck[i]);
}
}
Absolultely no sanity checks are done concerning the input. It's just for demonstration.

Your int argc is the count of arguments. So you can indeed manually load all of these cards into an array if you so choose.
Assuming you execute the program like this:
example.exe rummy 3 S1 S2 S3 S4 A1 A2 A3 A4
You could then read the cards into an array like this (assuming that "rummy" is game type and "3" is some other control variable, you need to make sure of this)
int main(int argc, char *argv[])
{
char game[10] = argv[0];
int players = atoi(argv[1]);
char deck[52][3]; // an array of strings max lenght 3 (2 characters + required '\0' terminator
for (int i = 0; i < argc - 2; i++) // argc - 2 because we're accessing at i+2 so the last iteration will essentially access the last element
{
strcpy(deck[i], argv[i+2]); // copy into actual array
}
return 0;
}
Now you got your cards in an array of char arrays called deck. Take note that this is completly only a sample and that it is not recommended for direct use. In an eventual program you must have sanity checks and validation against all possible cases (too many args, too little args, wrong args, etc.

All arguments passed on command line are stored in argv array. argv[0] is always the name of the program and next come your arguments if any (as null-terminated strings).
So assuming you have called this as:
rummy 3 S2 H9 C4
this is what argv contains:
argv[0] = "rummy"
argv[1] = "3"
argv[2] = "S2"
argv[3] = "H9"
argv[4] = "C4"
Inserting these into array is simple:
char args[5][10];
strncpy(args[0], argv[0], 10);

Related

Try to convert all strings in argv[] to integers and store them into a new array

I'm new to C and I'm trying to convert all strings that the user typed in the command line to integers and store them into a new array, so that I can use it later. But I get a "segmentation fault (core dumped)" issue.
Can someone check with my code and point out the error(s)?
int main(int argc, char *argv[]) {
long int conv[argc - 1];
for (int i = 0; i < argc; i++) {
conv[i] = strtol(argv[i + 1], NULL, 10);
}
If I run this program like, ./main 1 2 3, then {1, 2, 3} should be stored in the new array of integers.
The arguments you pass in to your program are stored in argv[1] to argv[argc-1], so you'd want to change the for loop to something like this: for (int i = 1; ...) {...}. Also, with strtol(argv[i+1],NULL,10);, when i==argc-1, you're trying to access the array out of bounds.
Here's a modified version of your code with the fixes applied:
int main(int argc, char *argv[]){
long int conv[argc-1];
for(int i=1;i<argc;i++){
conv[i-1]=strtol(argv[i],NULL,10);
}
}
Your loop attempts to access an "out-of-bounds" array element on its last iteration: if you run the program with, say, ./main 1 2 3, then argc will be 4 and the last argument will be in argv[3]. However, when the loop index, i is 3, the loop will still run and you will be attempting to read argv[i + i] – which is argv[4] and thus beyond the end of the array.
You can simplify your loop (or, at least, rewrite it) to use the actual i value for the argv index and i - 1 for the conv index; but, of course, you then need to start the loop with i = 1:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
long int conv[argc - 1];
for (int i = 1; i < argc; i++) {
conv[i - 1] = strtol(argv[i], NULL, 10);
}
// Data check:
for (int j = 0; j < argc - 1; ++j) {
printf("Data %d is %ld\n", j, conv[j]);
}
return 0;
}

scanf is not storing the full set of each line but is stopping at each period and then starting storing from a new line

i am tring to read in a series of network addresses similar to
168.12.110.25
64.113.134.35
217.158.91.183
102.130.129.146
215.116.26.223
81.162.78.0
19.204.25.222
245.124.138.157
137.249.183.201
106.61.236.67
106.71.236.60
106.81.240.63
168.14.111.27
168.17.111.27
215.116.26.220
137.249.111.202
137.246.111.202
and store them into netoworks, that has to be a two dimensional array.
//declare libraries
#include <stdio.h>
#include <stdlib.h>
//declare other functions/files to be used in the program
void print_fun(void);
int sort_fun(void);
void read_fun(void);
//read command line input and store the information
int main(int argc, char** argv){
unsigned char networks[argc][4];
int arg = 0;
//convert command line argument to int
arg = atoi(argv[1]);
for (int j =0; j<1; ++j){
if(argc == 1)
{
printf("ERROR ERROR, you messed up\n");
}
else
{
// hold network addresses in a 2-d array, with 4 unsig char
for(int k = 0; k<arg; ++k){
for (int i =0; i<4; ++i){
scanf("%hhu",&networks[k][i]);
printf("%hhu",networks[k][i]);
}
printf("\n");
}}}
//sort array
42 //count networks
//print info about the array
}
i am wondering what i am doing wrong. i need to store the information coming in from the file into networks, the scanf is not storing the complete information of each address.
the new output
[p18d541#csci112 program1]$ ./main 17 < inp17.txt
1680640
0000
11000
0000
2481141048
25512700
194000
2000
2311131048
25512700
2919640
17000
1601131048
25512700
1000
0000
20818640
how do i change my code to store the network properly.
EDIT
with a quick update to the code of adding a period on the scan and print.
//declare libraries
#include <stdio.h>
#include <stdlib.h>
//declare other functions/files to be used in the program
void print_fun(void);
int sort_fun(void);
void read_fun(void);
//read command line input and store the information
int main(int argc, char** argv){
unsigned char networks[argc][4];
int arg = 0;
//convert command line argument to int
arg = atoi(argv[1]);
for (int j =0; j<1; ++j){
if(argc == 1)
{
printf("ERROR ERROR, you messed up\n");
}
else
{
// hold network addresses in a 2-d array, with 4 unsigned char
for(int k = 0; k<arg; k++){
for (int i =0; i<4; i++){
scanf("%hhu.", &networks[k][i]);
printf("%hhu.\",networks[k][i]);
}
printf("\n");
}}}
//sort array
//count networks
//print info about the array
}
and the new output is,
[p18d541#csci112 program1]$ ./main 17 < inp17.txt
1681211025
6411313435
21715891183
102130129146
21511626223
81162780
1920425222
245124138157
137249183201
1066123667
1067123660
1068124063
Segmentation fault (core dumped)
or it has thousands of output.
it is random
scanf is having a hard time parsing the periods between the numbers, and it's causing it to behave in unexpected ways. Try this instead:
scanf("%hhu.",&networks[k][i]);
printf("%hhu",networks[k][i]);
You've also got an issue in your declaration of array size:
unsigned char networks[argc][4];
argc is how many arguments were passed into the function, not the actual value you passed. This means your array is going to be the wrong size, likely resulting in a segfault. Try this instead:
int arg = 0;
//convert command line argument to int
arg = atoi(argv[1]);
//declared AFTER we have the value we want
unsigned char networks[arg][4];

C converting character command line arguments to an integer array

I'm new to C and trying to figure out arrays and command line arguments. I have:
int main(int argc, int **argv) {
int vals[8];
for(int i = 0;i < 8;i = i + 1) {
vals[i] = atoi(argv[i]);
printf("%d", vals[i]);
}
}
I call it with ./file 1 2 3 4 5 6 7 8 and I would expect it to spit out 12345678, but instead, it spits out 01234567 which to me says that it's just printing the array positions. How do I get to actually print/access the value of vals[i], and/or make sure that the command line value is actually being properly assigned?
Thanks in advance.
Start with argv[1] In order to exclude the first element of argv which is the program name. A simple way to do this is to increment argv at the top of the program.
int main(int argc, char **argv) {
argv++; /* argv[0] is the program name */
int vals[8];
for(int i = 0;i < 8;i = i + 1) {
vals[i] = atoi(argv[i]);
printf("%d", vals[i]);
}
}
On a side note, you should check the value of argc prior to accessing elements at index i in argv
argv [0] is the name of the program.
The arguments start at 1. You should also get in the habit of using argc in loops.
int main(int argc, int *argv[])
{
for(int i = 1 ; i < argc ; ++ i )
{
int val = atoi(argv[i]);
printf("%d", val);
}
}

Need to change the Pointers make me problems

Hello I have a program the receiving parameters from the user. The transmission is performed using pointers.
The code later does not use pointers which creates a problem with what is received. I would be happy if you help me fix the code that will work.
code -
#include <stdlib.h>
#include<string.h>
void order(int n,char argv[99]);
int main(int argc, char** argv)
{
int i,n;
n = argc;
order(n,*argv);
}
void order(int n,char argv[99])
{
int i,j;
char temp;
for(i=1; i < n; i++)
{
for(j = 0 ; j < n - 1; j++)
{
if(argv[j] > argv[j+1])
{
temp=argv[j];
argv[j]=argv[j+1];
argv[j+1]=temp;
}
}
}
system("PAUSE");
for (i = 0; i < n ; i++)
{
printf("%c",argv[i]);
}
}
It appears you are confused about argc and argv.
int argc contains the number of command-line arguments passed to your program, char **argv is an array (null-pointer terminated even) of strings (null-byte terminated character arrays) containing these arguments. This is at odds with your program:
1. There is no reason to limit the length of any one command-line argument to 99 characters.
2. You pass only the first (zero-indexed) command-line argument to order(). This will usually be the name of the program.
3. You then use argc in order(). However, argc is not the length of the first command-line argument. That would be strlen(argv[0]).

Pointers & Dynamic Memory Allocation in C

I'm fairly new to the language C and am getting a bit muddled up with pointers & dynamic memory allocation. What I'm trying to do is read in command line arguments and store them in dynamic memory allocation; then printing them out. For example if I typed ./rpd 4 3 2 3 8 then argv[1] (4) should be decremented and the other 3 values (3, 2, 3, 8) should follow. The output should look like:
Person 1 has 3 cars.
Person 2 has 2 cars.
Person 3 has 3 cars.
Person 4 has 8 cars.
My Code is:
#include <stdio.h>
int main(int argc, char *argv[]) {
/** argc is number of arguments at command line*/
/** argv[] is an array of pointers to character strings
i.e. argv 1 points to argc 1 */
int numberOfCars;
char *person;
int i;
int j;
// Allocate the size of the array for each element of char
person = malloc(sizeof(numberOfCars) *argc);
for(i = 2; i < argc; i++) {
/** Convert char to int */
numberOfCars = atoi(argv[i]);
person = atoi(argv[1]);
if(person > 0){
for(j = 2; j < person; j--) {
printf("Person %d has %d cars \n", person--, numberOfCars);
}
} else {
/** DO NOTHING */
}
}
return person;
}
I'm sorry if this is a little confusing (or naive) of me; but I am extremely new to this language so I'm still trying to get my head around everything.
Thanks alot for any help :)
Try something like this:
#include <stdio.h>
int main(int argc, char *argv[]) {
/** argc is number of arguments at command line*/
/** argv[] is an array of pointers to character strings
i.e. argv 1 points to argc 1 */
int numberOfCars;
int i;
for(i = 1; i < argc; i++) {
/** Convert char to int */
numberOfCars = atoi(argv[i]);
printf("Person %d has %d cars \n", i, numberOfCars);
}
return 0;
}
Then tweak it for your needs. You dont need to specify the number of people for the first input argument, since it's implied by the number of cars you specify for each person.
Code
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int numberOfCars;
int *person;
int i;
person = malloc(sizeof(int) * argc);
for(i = 1; i < argc; i++)
{
numberOfCars = atoi(argv[i]);
if (i == 1)
numberOfCars--;
person[i] = numberOfCars;
printf("Person %d has %d cars\n", i, numberOfCars);
}
free(person);
return 0;
}
Sample output
$ ./rpd 4 3 2 3 8
Person 1 has 3 cars
Person 2 has 3 cars
Person 3 has 2 cars
Person 4 has 3 cars
Person 5 has 8 cars
$
Explanation
#include <stdio.h>
#include <stdlib.h>
You need <stdlib.h> to declare malloc() and free(). When you use malloc(), you should also use free().
int main(int argc, char *argv[])
{
int numberOfCars;
int *person;
int i;
The variable j is unused in the revision and therefore removed. The variable person is changed to int * as person[i] will store the number of cars person i has.
person = malloc(sizeof(int) * argc);
I changed the sizeof() to int; it would also be possible to use sizeof(*person) and there are good reasons for preferring that.
for (i = 1; i < argc; i++)
{
numberOfCars = atoi(argv[i]);
The assignment person = atoi(argv[1]); was erroneous at multiple levels. It leaked the memory assigned by the malloc(); it assigned an int to a pointer (originally a char *).
if (i == 1)
numberOfCars--;
This deals with the 'subtract one from first argument' requirement.
person[i] = numberOfCars;
This records the number of cars that person i has. It isn't used; it could be used in place of numberOfCars in the printf() statement.
printf("Person %d has %d cars\n", i, numberOfCars);
Spaces at the end of a line are a bête noire of mine. Don't put blanks before a newline.
}
free(person);
Release the memory that was allocated. In this toy program, it isn't critical (the o/s is about to release all the resources used by the program), but if it was a function in a big program and it omitted the free(), it would leak memory each time it is called. Get into the habit of writing the free() for each malloc() as soon as you've written the malloc(). (Or, at least, make sure you know where you will write the free(), and do write the free() before compiling, let alone testing, the program.)
return 0;
}
What do you want to store dynamically?
If want to only print the values as you mentioned in question. You would not require dynamic allocation at all.
If at all you want to store them use
char **person; //instead of *person and keep allocation memory per person by using
person[i] = malloc(sizeof(argv[i])+sizeof("person has cars")); //not sure of ur required format to store you can change it accordingly
atoireturns an int, but person is a char pointer.
#include <stdio.h>
int main(int argc, char *argv[]) {
/** argc is number of arguments at command line*/
/** argv[] is an array of pointers to character strings
i.e. argv 1 points to argc 1 */
int numberOfCars;
int i;
int p = 0;
for(i = 2; i < argc; i++) {
/** Convert char to int */
numberOfCars = atoi(argv[i]);
printf("Person %d has %d cars \n", ++p, numberOfCars);
}
return 0;
}
Output:
$ ./a.out 4 3 2 3 8 10
Person 1 has 3 cars
Person 2 has 2 cars
Person 3 has 3 cars
Person 4 has 8 cars
Person 5 has 10 cars

Resources