-
Print argv array
Trying to write a program that sorts names using an algorithm. I can not get the initial array to print properly, I feel like it's something simple that I'm missing. Sorry if I butchered it worse messing with the syntax.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void print_array(char [], int);
int main(int argc, char * argv[]){
print_array(* argv, (argc-1));
getchar();
return 0;
}
void print_array( char word[], int size){
int i = 0;
for( i = 0; i < size; i++){
if(i < (size - 1)){
printf("%c", word[i]);
}else{
printf("%c\n", word[i]);
}
}
}
-
argv is an array of pointers to char*, thus, *argv is just a pointer to char, it's equivalent to *(argv + 0) which is equivalent to argv[0]. So you are calling print_array with just the first element of argv (usually the name of the program).
We actually have a FAQ article that covers working with argv, and has an example that very nearly does what you want. Check out this link: FAQ > Accessing command line parameters/arguments - Cprogramming.com.
EDIT:
* Really, it's just a pointer to pointer to char, since arrays decay to pointers when passed to a function, and argv is a parameter passed to main, which is a function.
-
Thanks for FAQ, I understand more clearly how they work but I didnt' see much how to pass the elements to another function. I tried setting an initialized array to char * argv[] to no avail. Or must I print the array in main for it to execute properly?
-
Ahh, I get what you're after. Just make the argc and argv parameters in the other function look like the ones in main, then pass argc and argv from main to that function, no need for any extra *, [], etc. Like this:
Code:
#include <stdio.h>
void foo(int argc, char *argv[]) // looks just like the parameter to main
{
int i;
for (i = 0; i < argc; i++) { // now use them just like you would use them in main
puts(argv[i]);
}
}
int main(int argc, char *argv[])
{
foo(argc, argv); // pass the variables as-is, no need for extra "adornments"
return 0;
}
-
-
So, I am having a little trouble of writing my sorting algorithm. My primary questions is to access the specific element instead of the string i.e in the word john acess the j. Do I need to pass the argv[][] or will argv[] work, and if I need to two brackets, do I need to include that in my main function paraments?
-
Are you trying to sort each word in argv?
If so, then you need to pass the entire word. For example:
Code:
void sort(char *word, int len)
{
char tmp;
// sorting algorithm loops and such
// swap code
tmp = word[i];
word[i] = word[j];
word[j] = tmp;
}
int main(int argc, char *argv[])
{
sort(argv[3], strlen(argv[3])); // sort the 4th word in argv
}
If that's not what you want, you need to be more specific in what exactly you are trying to sort.
-
I apologize for the lack of clarity. I'm attemption to sort names alphabeticalls in order and reverse order. i.e. david, john, bob would have the output
In order:
Bob
David
John
Reverse order:
John
David
Bob
I have looked up some sorting algorithm code but am having trouble translating it to the name sort. My biggest issue is where or not I have to pass argv[][] to sort names that start with the same letter(s). For example, Andrew and Another would have to go to the [i][3] element before the sorting could be successfully completed.
-
Okay, so you need to sort the elements of argv. argv is essentially an array of char pointers, so you are just sorting an array of char pointers. You need something like this:
Code:
void sort(char *argv[], int argc)
{
char *tmp;
// sort algorithm loops
tmp = argv[i];
argv[i] = argv[j];
argv[j] = tmp;
}
int main(int argc, char *argv[])
{
...
sort(argv + 1, argc - 1); // this omits the first argument, which is the program name, and adjusts the length accordingly
...
}
-
Thanks, I've been tinkering with my algorithm for some time. I can't get any desired output. I'll paste my code for some tips on obvious flaw and if anyone has any links to some help on the topic I have google quite a bit wihtout much success.
Code:
void sort_in_order(int argc, char * argv[]){
int i, j;
char * temp;
for(i = 0; i < argc; i++ ){
for(j = i+1; j < argc; j++){
if(strcmp(argv[j],argv[i]<0))
{
temp = argv[i];
argv[i] = argv[j];
argv[j] = temp;
}
}
}
}
-
Code:
if(strcmp(argv[j],argv[i]<0))
Double check the placement of your parenthesis on this line.
-
Ah, thanks but my output remains the same as the original input.
-
Code:
if(strcmp(argv[j],argv[i]<0))
To move strings, strncpy/strcpy
Your program can not write to argv[n]
Remember that pointers are not arrays
Code:
temp = argv[i];
argv[i] = argv[j];
argv[j] = temp;
-
Ok, so my program is starting to move in the right direction but I've hit a stumper.
The display is
In order:
andrebob
bob
w
w
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void print_array(int, char * []);
void sort_in_order(int, char * []);
int main(int argc, char * argv[]){
printf("Before sorting:\n");
print_array(argc-1, argv+1);
sort_in_order (argc, argv);
printf("In order:\n");
print_array(argc, argv);
getchar();
return 0;
}
void print_array(int argc, char * argv[]){
int i = 0;
for( i = 1; i < argc; i++){
if(i < (argc-1)){
printf("%s\n", argv[i]);
}else{
printf("%s\n", argv[i]);
}
}
}
void sort_in_order(int argc, char * argv[]){
int i, j;
char * temp;
for(i = 0; i < argc; i++ ){
for(j = i+1; j < argc-1; j++){
if(strcmp (argv[j],argv[i])<0){
strcpy(temp,argv[i]);
strcpy(argv[i],argv[j]);
strcpy(argv[j],temp);
}
}
}
}
-
With the input of bob, david, john, andrew if that helps with advice.
If not, if anyone knows of some sources that have info on this topic it would be appreciated. I'm struggling to find quality source on the particular issues
-
Code:
void sort_in_order(int argc, char * argv[])
{
char * temp;
...
strcpy(temp,argv[i]);
You don't allocate memory for "temp", thus you can't copy a string to it.
But copying the strings is the wrong approach. You need to modify the pointers.
argv[n] is a pointer to a string, i.e. it points to the memory location where the first character of the string is stored. Now it looks like your implementation stores the command line arguments consecutively like:
Code:
b o b \0 d a v i d \0 j o h n \0 a n d r e w \0
^ ^ ^ ^
1 2 3 4 (argv-indices)
Now if you swap for example argv[1] and argv[4] like you do in your sort function (using strcpy()) the result will be:
Code:
a n d r e w \0 i d \0 j o h n \0 b o b \0 e w \0
^ ^ ^ ^
1 2 3 4
As you can see you have just swapped the contents, but the pointers (argv[1], argv[2], ...) will still point to the same memory location as before. That's why you print out garbage and why you need to rearrange the pointers instead.
Bye, Andreas
-
That makes alot of sense but I think I am struggling to entirely implement that into my code. I've removed strcpy and have rearragned the pointers to the strings but it just swaps the first letters of all the names and the rest of the string says in the exact same order.
Code:
void sort_in_order(int argc, char * argv[]){
int i, j;
char * temp;
for(i = 1; i < argc-1; i++ ){
for(j = i+1; j < argc-1; j++){
if(argv[i] < argv[j]){/*I know the if statement is wrong but I'm working on the words rearragning as a whole*/
*temp = *argv[i];
*argv[i] = *argv[j];
*argv[j ]= *temp;
}
}
}
}
Also, for doing rearraging the pointers do I still need to allocate memory for temp or is that only when you are copying data to temp? I have tried both ways with the same results.
-
First, you're a bit inconsistent in when and how you use argc or argc-1 and argv or argv+1 (or, you were in your last complete post, #14). Pick one method and stick to it. I recommend your functions don't try to adjust anything by +/- 1, that way they will work generically for any array of char *, should you want to reuse your print or sort functions. Always correct for this in main by passing in argc-1 and argv+1 to the functions. This effectively passes in a sub-array that starts at argv[1] instead of argv[0].
Code:
// in main
printf("Before sorting:\n");
print_array(argc-1, argv+1); // adjusted in main
sort_in_order (argc-1, argv+1); // adjusted in main
printf("\nIn order:\n");
print_array(argc-1, argv+1); // adjusted in main
...
void print_array(int argc, char * argv[]){
int i;
for( i = 0; i < argc; i++){ // note, start at 0 and go up to < argc, don't try to skip the first element here, you've already adjusted in main
printf("%s\n", argv[i]);
}
}
All those *s before temp, argv[i] and argv[j] are the problem. Remember, temp, argv[i] and argv[j] are pointers to char, so putting a * in front of them dereferences that pointer and gives you the single char it points to, i.e. the first letter of each argument. As a side note, temp is a pointer, but it is never set to point to valid memory, so when you do the following:
Code:
*temp = argv[i];
argv[j] = *temp;
You are reading from and writing to memory you might not own or have access to. This results in undefined behavior, which may mean a crash/seg fault, garbled output, or any number of other things. Never dereference a pointer unless it points somewhere valid.
Go back and look at post #10. Your compare and swap were correct there, but I think your sorting loops were wrong. You did
Code:
for(i = 1; i < argc-1; i++ ){
for(j = i+1; j < argc-1; j++){
You need to start i at 0, since you skip first element by passing in argv+1. Also, you need to stop at i < argc-1, since j = i+1, and this will cause a buffer overflow on the last iteration, where you will be comparing/sorting/swapping garbage. j, on the other hand, should start at i+1, and stop at j < argc. That makes j iterate over all elements after i.
Code:
for (i = 0; i < argc - 1; i++) {
for (j = i + 1; j < argc; j++) {
That should about do it.
-
If you are going to be doing anything with argv other than reading from it, it's worthwhile to make a copy of it.
-
Thanks anduril for the help, I think the lack of consistency in my program caused a lot of unnecessary confusion. I've got the program to sort in and reverse alphabetical order so I appreciate it.
And thanks to matticus I went over all the comment from everyone. He said check my parenthesis in
Code:
if(strcmp(argv[i],argv[j]<0))
If I figured out my mistake in that sooner I might of been able to get by without asking so many extra questions :wink: