C Programming Reading Chars from the Command Line - c

Let's say I type in $./file ABCDEFG into the command line and I want to store chose as individual chars in an array in my file. Based on my research it should look something like this but it is not giving me any output. The nextChar is calling a different function and can be ignored here.
int main(int argc, char * argv[]) {
int i = 0;
char findThisString[argc];
while(i < argc){
findThisString[i] = argv[i];
i++;
printf("%c \n", findThisString[i]);
}
while(c != EOF){
nextChar();
}
}

first: char findThisString[argc]; . don't do staff like that. when you declare an array the compiler will need to know the size of the array to find and save place for the array. use pointers, malloc and free. this an undefined behavior that only allowed in C99.
second: findThisString[i] = argv[i]; . you declared one of them as an array of strings (char*) and another as an array of chars (char).
third: did you declared nextChar somewhere?? use getchar instead.
forth: you write int i=0; while(...){...; i++; }. this is not an error but when you are writing this loop like this it is better to write
for(int i=0; i<argc; i++).

Related

C error: Exited with non-zero status

I know this code is quite simple; but that message won't stop appearing, can you help me find where the error is?
#include <stdio.h>
void Reverse(char * word[]) {
char temp = word[0];
for (int i = sizeof(word); i >= 0; i--){
for (int j = 0; j<= sizeof(word); j ++){
word[0] = word[i];
}
}
word[sizeof(word)] = temp;
printf("%s", word);
}
void main() {
Reverse(gets(stdin));
return 0;
}
gets returns char*. In this context - It is wrong to write char *[] in the function definition where you are supposedly passing a char array where input characters are being stored using gets. Also char *gets(char *str) - you need to pass a buffer to the gets where the inputted letters will be stored. You didn't pass one.
sizeof doesn't work here. It returns the size of a pointer (char*). You will have to use strlen() to get the length of the string inputted by gets.
More importantly - don't use gets - it's time to use something much safer than gets, namely fgets etc. Buffer overflow is not something you want to deal with.
Suppose you are passing an array of char* to the function reverse. Then the parameter would be char*[] which means nothing other than char** here. Here you will simply pass the char array which you will be using as buffer to gets.

Reading array of string in C

I need to read an array of n strings from 2 letters in each (e.g. n = 3, need to read something near "ab bf cs"). I use this code and get segmentation fault:
int n;
scanf("%d", &n);
char array[n][2];
char *tmp;
for (int i = 0; i < n; i++)
{
scanf("%s", &tmp);
strcpy(array[i], tmp);
}
Please help me to fix it!
Problem 1
To store a string of length 2, you need a char array of size 3. Use:
char array[n][3];
Problem 2
You are using &tmp in the call to scanf. That is wrong on two accounts.
The type is not appropriate. Type of &tmp is char**. scanf needs a char* with the %s format specifier.
&tmp cannot hold a string.
You could use
scanf("%s", tmp);
That will be OK from type point of view but it won't ok from run time point of view since tmp does not point to anything valid.
You can do away with tmp altogether and use:
scanf("%s", array[i]);
That entire block of code can be:
int n;
scanf("%d", &n);
char array[n][3];
for (int i = 0; i < n; i++)
{
// Make sure you don't read more than 2 chars.
scanf("%2s", array[i]);
}
There are a couple things you need to fix here.
Remember that one "string" (char[]) always ends with a null terminating character \0. So, whenever you create a char[], you must leave enough space for that. For example:
char str[3] = "foo"; looks like ['f', 'o', 'o'], but
char str[4] = "foo"; looks like ['f', 'o', 'o', '\0'].
Unexpected consequences can occur when using the former.
This means that you should change char array[n][2] to char array[n][3].
Remember that pointers are different than arrays. If you want to use a pointer, you must allocate memory for it, otherwise you will most likely seg fault.
In your program, it's simple enough that you can probably get away with not using a pointer, especially since you know the the length of each string that you will be storing (2).
You could change char *tmp to char tmp[3].
You can actually refactor your code so you don't need the tmp variable at all. If you want, you can just store the word you read into the array directly. For example:
scanf("%s", array[n]);
If you are really insistent on using that tmp variable as a char *, then allocate memory for it, like so:
char *tmp = (char*)malloc(3 * sizeof(char));
As a sidenote, if you are adhering to the ISO C90 standards, you shouldn't intermix variable declarations in code, so in your loop where you have for(int i = 0...), you should declare int i; at the top of the file, and then assign it in the loop for(i = 0...).
First, as user3121023 pointed out in the comments, char *tmp; creates a pointer without memory allocated to it. scanf() needs an array, and you need space for the terminating '\0' (which is probably the source of your segmentation fault). So you could try scanf("%s", array[i]);.
Second, it's a good idea to use "%2s" instead of "%s" so the user doesn't input 3 digits and overflow your buffer.
Here's one solution.
int n;
scanf("%d", &n);
char array[n][3];
for (int i = 0; i < n; i++)
{
scanf("%2s", array[i]);
}

Value was not retained outside of a function

I'm writing a program that should get its inputs from a text file by using input redirection in a function called GetInput. (The text file contains 10 words.) The code should then be able to print the contents of ListWord in the Print function.
This is what I have so far.
I keep on getting errors while trying to run this code. I tried to remove * before ListWord and the code works but it does not retain the word (string) that was stored in it. But removing * before ListWord does not make sense to me. What am I doing wrong?
void GetInput( char** ListWord)
{
int i=0;
char word[30]; //each word may contain 30 letters
*ListWord = malloc(sizeof(char*)*10); //there are 10 words that needs to be allocated
while(scanf("%s", word)==1) //Get Input from file redirection
{
*ListWord[i]= (char *)malloc(30+1);
printf("%s\n", word); //for checking
strcpy(*ListWord[i], word);
printf("%s\n", *ListWord[i]); //for checking
i++;
}
}
void Print(char *ListWord)
{
//print ListWord
int i;
for (i=0; i<10; i++)
{
printf("%s", ListWord[i]);
}
}
int main()
{
char * ListWord;
GetInput(&ListWord);
printf("%s\n", ListWord[0]);
Print(ListWord);
free(ListWord);
return 0;
}
(Note: This is a homework. Thank you and sorry if it's unclear)
Due to *operator precedence the expression *ListWord[i] doesn't do what you think it does. In fact you should be getting errors or warnings from the code you have.
The compiler thinks that *ListWord[i] means *(ListWord[i]), which is not right. You need to use (*ListWord)[i].
Unfortunately that's only the start of your problems. A bigger problem is that the pointer you pass to the function GetInput is not a pointer to what could become an array of strings, but a pointer to a single string.
For a dynamic allocated array of strings, you need a pointer to a pointer to begin with, and then emulate pass-by-reference on that, i.e. you need to become a three star programmer which is something you should avoid.
Instead of trying to pass in the array to be allocated as an argument, have the GetInput return the array instead. Something like
char **GetInput(void)
{
// Allocate ten pointers to char, each initialized to NULL
char **ListWords = calloc(10, sizeof(char *));
if (ListWords == NULL)
return NULL;
char word[31];
for (int i = 0; i < 10 && scanf("%30s", word) == 1; ++i)
{
ListWords[i] = strdup(word);
}
return ListWords;
}
The above code adds some security checks, so you will not go out of bounds of either the temporary array you read into, or the ListWords array. It also makes sure the ListWords array is initialized, so if you read less then 10 words, then the remaining pointers will be NULL.
Of course you need to change your main function accordingly, and also your Print function, because now it only takes a single string as argument, not an array of strings. You also of course need to free every single string in the array because freeing the array.

Create an Array of Strings from an Array of Ints in C

I'm attempting to convert an array of ints to an array of strings in c. My code so far is:
int args[] = {1, 3000};
char *str_args[15];
int i = 0;
for(i; i<=((sizeof(args)/sizeof(args[0]))); i++){
char buffer[10];
sprintf(buffer, "%d", args[i]);
str_args[i] = buffer;
}
printf("%s\n", *str_args[0]);
This code causes my program to crash instead of outputting 1 (the first arg) like I expect. What am I missing here? Thanks in advance
It's because you assign each entry of str_args to a local pointer, one that goes out of scope once the loop loops.
You might want to consider strdup:
str_args[i] = strdup(buffer);
Of course, you then have to free the memory allocated by strdup.
You also have a problem when printing just after the loop, when you want to print a string, but *str_args[0] dereferences the first string. i.e. it's the first character and not a string. Remove the dereferencing operator * and it should work just fine.
On the printf, the datatype of the parameter is incorrect
Also you need to copy temporary "buffer" to allocated memory or each loop overwrites the next
Code below fixes these two problems
#include<stdio.h>
#include<string.h>
main() {
int args[] = {1, 3000};
char *str_args[15];
int i = 0;
for(i; i<=((sizeof(args)/sizeof(args[0]))); i++){
char buffer[10];
sprintf(buffer, "%d", args[i]);
str_args[i] = strdup(buffer);
}
printf("%s\n", str_args[0]);
}
for(i; i<=((sizeof(args)/sizeof(args[0]))); i++){
should be :
for(i=0; i<((sizeof(args)/sizeof(args[0]))); i++){//take out the `=` after >, add i=0 first.
As the way it is originally written, i will reach 2, and cause the overrun you experienced.
(i=0 is optional since you have i initialized in the line before, but its better form to just do it in the for loop.)
You are overrunning your buffers otherwise. BTW, you do realize that there are only two items in the following array, right?
int args[] = {1, 3000};

Basic C Pointer

I'm a beginner in C and have been trying to figure out what has gone wrong with my code code for the past hour or two. I have been following through K&Rs book and I keep looking through it but still do not understand my logic mistake.
while (*argv>0){
while (**argv>0){
printf("%c\n",**argv);
**argv++;
}
argv++;
}
Task:Print out all the arguments being fed to my program using argv.
To my understanding, argv is a pointer to an array that contains further pointers to arrays of character pointers. So, I said that while *argv>0 or while the first array still has elements, we should follow the pointers from the first array to the next array. Then we should print out all the elements in the next array.
Too many * in this line:
**argv++;
It should be like this:
*argv++;
Plus additional braces, because the ++ operation has higher priority:
(*argv)++;
And it will work.
I suggest you don't confuse yourself by using pointer dereferencing the way you do when the subscript notation ([]) allows you to do the same.
#include <stdio.h>
int main(int argc, char** argv)
{
int i;
for(i = 0; argv[i]; i++)
printf("%s\n", argv[i]);
return 0;
}
This will also print argv[0], which is the name/path of the program.
Now what does my code do? for(i = 0; argv[i]; i++) counts up i from 0 to the element when argv[i] resolves to false (i.e. 0 aka NULL), that is the last element of the argv array. And then for every element in the array it uses the %s format specifier of printf to print it. You could also pass the argv[i] as the first and only parameter to printf, but that is usually frowned upon as it opens the door for certain string formatting attacks.
argv is of type char *argv[] i.e. a pointer to an array of strings (char*'s). argv++ moves to the next string in the array.
Usually this function would be written as follows:
int main(int argc, char *argv[]){
int i;
for (i = 0; i < argc; i++){ //loop from 0 to argc (argument count)
printf("%s ", argv[i]);
}
return 0;
}
this will work::
while(argc--)//can't use *argv here, because *argv would be the address of the
// element which argv is pointing to, just by knowing the address u can't say whether it still has elements or not
{
while( **argv )
{
printf("%c", **argv);
(*argv)++; //by using **argv++, you are actually moving argv to next array, not to the next character of current array
}
argv++;
printf("\n");//move your \n to here, else you will end up printing every character in a new line
}

Resources