Converting 'integer strings' to integer array - c

I'm trying to pass in an array of integers into my program. Is there a better way to convert it to integers? I'm currently getting an error: "Variable sized object may not be initialized"
for(i = 0; i < argc; i++)
{
int arr[i] = atoi(argv[i]);
}

Assuming argc and argv are the arguments passed to main, it is unlikely that argv[0] is something that you want to convert into an integer. argv[0] usually contains the name of the program.
Your code snippet is declaring an array local to the loop body. What you likely want is an array defined outside the loop body, and you want to assign to individual array elements within the loop body.
int arr[argc];
for(i = 1; i < argc; i++)
{
arr[i] = atoi(argv[i]);
}

You are declaring your array arr every time you loop.
change your loop like this:
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
int arr[argc];
int i=0;
for(i = 0; i < argc-1; i++)
{
arr[i] = atoi(argv[i+1]);
printf("arr[%d] = %d\n",i,arr[i]);
}
return 0;
}
Here is the output:
Sukhvir#Sukhvir-PC ~
$ gcc -Werror -Wall -g -o test test.c
Sukhvir#Sukhvir-PC ~
$ ./test 3 4 5
arr[0] = 3
arr[1] = 4
arr[2] = 5

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;
}

GCC Compilation Error on array assignment

I am trying to convert a string into its equivalent matrix form in C. The matrix would have 3 rows and as many columns as required. The following code doesn't compile, and I haven't figured out what's going wrong.
The error that GCC throws is:
app.c:10:25: error: subscripted value is not an array, pointer, or vector
printf("%d\n", arr[i][k]);
~~~^~
1 error generated.
Main file (app.c):
#include <stdio.h>
#include "converter.h"
int main() {
char source[] = "This is the source. "; // placeholder text
int arr = convert(source);
for (int i = 0; i < 21; i++) {
for (int k = 0; k < 3; k++) {
printf("%d\n", arr[i][k]); // error occurs at this line.
}
}
return 0;
}
converter.c file:
// Converts an input string to its respective ASCII matrix.
#include <string.h>
#include <stdio.h>
#include "converter.h"
// Converts the entire string into an multi-dimensional array.
int convert(char text[]){
// copy the input text into a local store.
char store[strlen(text)];
strcpy(store, text);
// make sure the length of the input string is a multiple of 3 or make it so.
int excess = strlen(store)%3;
char excess_spaces[3] = " ";
if (excess != 0) {
strncat(store, excess_spaces, 3-excess);
}
// covert the source into an array
int arr[3][strlen(store)/3];
int steps = strlen(store)/3;
for (int i = 0; i < steps; i++) {
int t[3];
for (int k = 0; k < 3; k++) {
t[k] = (int) store[3*i+k];
arr[k][i] = t[k];
}
}
return arr;
}
converter.h file:
int convert(char text[]);
There are multiple issues in this code.
The allocating storage for string, one must include one byte for a null terminator. Replace:
char store[strlen(text)];
with:
char store[strlen(text) + 1];
Additionally store must be big enough to contain the excess which is up to 3 spaces.
char store[strlen(text) + 3 + 1];
In C you cannot use an array as a value. It is converted to a pointer to it's first element in pretty must every context. Therefore it is not possible to return an array directly. It could be workaround by wrapping an array with a struct but it a topic for another day.
As result return arr will be equivalent to return &arr[0] which is int (*)[XXX] a pointer to int array of size XXX.
Never ever return a pointer to an object with automatic storage. It's Undefined Behaviour. I know that the intention was returning an array not a pointer to it. Create an object with dynamic storage with malloc-like function to safely return a pointer.
Returning Variable Length Array (VLA) by value is not possible because Variably Modified (VM) types cannot be defined at file scope.
It looks that indices are swapped in:
printf("%d\n", arr[i][k]);
I guess it should be arr[k][i].
Now... let's solve it.
Returning VLA is tricky. One solution is to pass a pointer to VLA as an argument. See https://stackoverflow.com/a/14088851/4989451.
The issue with this solution is that the caller must be able to compute the dimensions.
The other way it to wrap the result of the convert() to a struct. Note that the function and the struct can share the name. The result with have the sizes of VLA as n and m members and the pointer to the data as arr. The caller need to cast it to proper VM type.
To cumbersome casts between the non-trivial pointer types, one can cast via void*.
When all work with the array is done, release it memory with free().
// Converts an input string to its respective ASCII matrix.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
// Converts the entire string into an multi-dimensional array.
struct convert {
int n, m;
int *arr;
} convert(char text[]){
// copy the input text into a local store.
size_t textlen = strlen(text);
char store[textlen + 3 + 1];
strcpy(store, text);
// make sure the length of the input string is a multiple of 3 or make it so.
int excess = textlen % 3;
char excess_spaces[3] = " ";
if (excess != 0) {
strncat(store, excess_spaces, 3-excess);
}
size_t storelen = strlen(store);
// allocate VLA with dynamic storage
int (*arr)[storelen / 3] = malloc(3 * sizeof *arr);
// covert the source into an array
int steps = storelen / 3;
for (int i = 0; i < steps; i++) {
int t[3];
for (int k = 0; k < 3; k++) {
t[k] = (int) store[3*i+k];
arr[k][i] = t[k];
}
}
return (struct convert){ .n = 3, .m = steps, .arr = (int*)arr };
}
int main() {
char source[] = "This is the source. "; // placeholder text
struct convert res = convert(source);
int n = res.n, m = res.m;
int (*arr)[m] = (void*)res.arr;
for (int i = 0; i < n; i++, puts("")) {
for (int k = 0; k < m; k++) {
printf("%d ", arr[i][k]); // error occurs at this line.
}
}
free(arr);
return 0;
}

C: ERROR After mallocing and passing 2D char array to function

I don't understand what is wrong with the code below. It should malloc a 2D char array[5][30] (referred as LENGTH), pass it to a function and fill it with a string. It works just fine in the function; I can print it from there without any problem. But i cannot print even the first one from within the main() function (the application crashes if I try).
Could somebody please explain what I am doing wrong?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LENGTH 5
void fillArray(char array[][LENGTH]) {
for (int i = 0; i < 5; i++) {
strcpy(array[i],"Hi World");
}
for (int i = 0; i < 5; i++) {
printf("%s\n",array[i]);
}
}
int main() {
char** array = (char**)malloc(5*sizeof(char*));
for (int i = 0; i < 5; i++) {
array[i] = (char*)malloc(LENGTH);
}
fillArray(array);
printf("%s",array[0]);
getchar();
return 0;
}
From main() function you are passing double pointer array and catching with 2D array array[][LENGTH] which is not correct, just saying double pointer is not similar to 2D array & vice versa.
for your task in fillArray() use array of char pointer as a argument, how many ? LENGTH.
void fillArray(char *array[LENGTH]) { /* this is okay */
for (int i = 0; i < 5; i++) {
strcpy(array[i],"Hi World");/*now in `array[i]` you can store any no of char. */
}
for (int i = 0; i < 5; i++) {
printf("%s\n",array[i]);
}
}
Also casting malloc() is not required And once job is done at last don't forget to free the dynamically allocated memory by calling free() for each.
The basic problem is that your function expects a 2 dimensional array but that is not what you pass to the function.
In main you allocate a 1 dimensional array of pointers. Then for each of these pointers, you allocate a 1 dimensional array of chars. That is not a 2D array.
So your function doesn't get what it expects and therefore your program fails.
So instead of:
char** array = (char**)malloc(5*sizeof(char*));
for (int i = 0; i < 5; i++) {
array[i] = (char*)malloc(LENGTH);
}
try this:
char (*array)[LENGTH] = malloc(5*LENGTH*sizeof(char*));
to get a correctly malloc'ed 2D array.
BTW:
I think you have a bug here
#define LENGTH 5
^
I guess you want 30 instead of 5

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);
}
}

Pointers to the same location

I have been struggling with this for quite some time now.
While copying array of strings like in the following code:
#include <stdio.h>
int main (int argc, char* argv[])
{
int i = 0;
for (i = 0; i < argc; i++)
{
printf ("%d: %s # %p \n",i,argv[i],argv[i]);
}
char* states[7];
for (i = 0; i <argc; i++)
{
states[i] = argv[i]; // line 36
printf ( "State no.%d: %s # %p \n", i ,states[i],&states[i]);
}
return 0;
}
I obtain the following output:
OUTPUT:
0: ./ex1 # 0x7fff651da366
State no.0: ./ex1 # 0x7fff651d94d0
Shouldn't both the addresses in the output be the same as on line 36 of the code I am making both the pointers point to the same address?
The expression &states[i] gives you the address of where states[i] is in memory, and not where it's pointing. Drop the address-of operator to fix the problem.

Resources