C programming find length of 2 Dimensional array - c

My program grabs command line arguements with argc and argv[]. My question is how can I find the length of argv[1][i].
My code that grabs length of argv[]
int my_strlen(char input[]){
int len = 0;
while(input[len] != '\0'){
++len;
}
return len;
}
but when I try to find argv[1][len] I get a subscripted value is neither array nor pointer:
my attempt
int my_strlen(char input[]){
int len = 0;
while((input[1][len] - '0') != '\0'){
++len;
}
return len;
}
FULL CODE:
#include <stdio.h>
#include <math.h>
int my_strlen(char input[]);
int main(int argc, char *argv[]){
int length = 0;
length = my_strlen(argv[1]);
long numberArr[length];
int i, j;
for(i = 0; i < length; i++){
numberArr[i] = argv[1][i] - '0';
}
return 0;
}
int my_strlen(char input[]){
int len = 0;
while((input[1][len] - '0') != '\0'){
++len;
}
return len;
}
Thanks for any help in advance!

I think you're confused about the argv content. The OS will pass a number of ASCIIZ strings, such that invoking my_program with arguments ala...
my_program first second third
...is similar to having the following declaration in your program...
int argc = 4;
const char* argv[4] = { "my_program", "first", "second", "third" };
Hence, when you index into argv[1][i] you're getting the i-th character in the string "first". That's only valid for values of i between 0 (which yields 'f'), and 5 (which indexes to the terminating NUL character '\0').
So, there no two-dimensional N*M array, but there is an array of pointers-to-(array-of-char). You can invoke the normal strlen() function as in strlen(argv[1]) to find out the number of characters in each argument. Only argc tells you the total number of elements in argv.
Does that help?

In main, you're passing argv[1] to my_strlen. That means my_strlen just receives a normal, single-dimension string. It doesn't need to do input[1][len], just input[len].

Related

Segmentation Fault when trying to populate array of strings in C

int main() {
const char* text = "the quick brown fox jumps";
int* argc = 0;
char *argv[] = {};
printf("%d", parse_command(text, argc, argv));
}
int parse_command(const char *inp, int *argc, char *argv[]) {
int offset = 0;
int count = 0;
int i = 0;
bool bool1 = true;
while (*(inp + offset) != '\0') {
if (inp[i] == ' ')
bool1 = true;
if (bool1 && inp[i] != ' ') {
bool1 = false;
argv[i] = &inp[i];
++count;
}
++offset;
i++;
}
*argc = count;
return count;
}
I am trying to split the character array inp into words, and return the number of words. What is considered a word is: a sequence of non-blank characters ending in one or more blank spaces. I want argc to be set to the number of words (which I think works fine), and argv[0] should point to the first character of the first word, argv[1] to the first character of the second word, and so on.
I keep getting segmentation fault error. Is this because char* argv[] is empty when initialized? If so, how can I initialize it to a specific length?
When you declare int *argc = 0 you are creating a pointer, and setting its value to 0.
Then dereferencing this pointer is invalid as it is a null pointer, which results in a segfault.
What you can do is create an integer (int argc = 0) and pass it by reference to the function (&argc).

Iterate through every char in string stored in an array

I am really new to C and in my first half year at university. This is my first questio on StackOverflow.
My task is to program it so every string stored in numbers is being converted into a decimal, without changing anything outside the main function.
I am now trying for the past 4 hours to solve this problem, where I want to iterate trough every char in the string I am currently to then, based on there position in comparison to the length to convert it into a decimal.
My only question here is to someone help me to understand how I can get the string length without using strlen() due to the fact I can't add #include <string.h>
This is what I got so far (getting the length of the array to iterate through every index):
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
// Add here..
int length = sizeof(numbers);
for ( int i = 0; i < length; i++ ){
//how do i get the string size without strlen() D:
}
return 0;
}
In C, strings are really just char arrays with a special terminator character to mark the end of the string. So, say you have something like:
char *str = "hello";
This is essentially equivalent to this:
char str[] = {'h', 'e', 'l', 'l', 'o', '\0'};
Notice that \0 character at the end of the array? This is the special terminator character that C places at the end of strings. Functions like strlen() pretty much iterate through the char array looking for the first occurrence of the \0 character and then stopping.
So, you can make your own version of strlen(), say my_strlen() like this:
int my_strlen(char *str)
{
/* Initialize len to 0 */
int len = 0;
/* Iterate through str, increment len, and stop when we reach '\0' */
while(str[len] != '\0')
len++;
/* Return the len */
return len;
}
Then within your for loop, you can just call this function. Also, note that your calculation of the size of the numbers array:
int length = sizeof(numbers);
will not give you the number of elements in the array. That code gives you the size (in bytes) or numbers which is an array of char pointers. If you want to get the number of elements, you have to divide that size by the size (in bytes) of a single element (i.e., a char pointer). So, something like this would work:
int length = sizeof(numbers) / sizeof(numbers[0]);
Your final code can look something like this:
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int my_strlen(char *str) {
/* Initialize len to 0 */
int len = 0;
/* Iterate through str, increment len, and stop when we reach '\0' */
while(str[len] != '\0')
len++;
/* Return the len */
return len;
}
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
// Add here..
// Notice the change here
int length = sizeof(numbers) / sizeof(numbers[0]);
for(int i = 0; i < length; i++ ){
int str_len = my_strlen(numbers[i]);
// Do what you need with str_len
}
return 0;
}
This project can be done without computing the length of the strings. How? In C, all strings are nul-terminated containing the nul-character '\0' (with ASCII value 0) after the last character that makes up the string. When you need to iterate over a string, you just loop until the character values is 0 (e.g. the nul-character)
This is how all string function know when to stop reading characters. Since you have an array-of-pointers that contains your strings, you just need to loop over each pointer and for each pointer, loop over each character until the nul-character is found.
Putting it altogether, (and noting you don't need math.h), you can do:
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
int nnumbers = sizeof numbers / sizeof *numbers; /* no. of elements */
for (int i = 0; i < nnumbers; i++) {
long long unsigned number = 0;
/* you don't care about the length, strings are nul-terminated,
* just loop until \0 is found.
*/
for (int j = 0; numbers[i][j]; j++) {
number <<= 1; /* shift left */
number += numbers[i][j] == '1' ? 1 : 0; /* add bit */
}
printf ("%s = %llu\n", numbers[i], number); /* output result */
}
return 0;
}
(note: you must use a 64-bit type to hold the converted values as "1010110011010101111101111010101110110" requires a minimum of 38 bits to represent)
Example Use/Output
Simple example output converting each string to a numeric value:
$ ./bin/binstr2num
01001001 = 73
00101010 = 42
010100111001 = 1337
011111110100101010010111 = 8342167
0001010110011010101111101111010101110110 = 92790519158
01011100110000001101 = 379917
#include <stdio.h>
int main(){
char arr[20]="Hello";
int count=0;
while(arr[count]!='\0'){
count++;
}
printf("%d",count);
return 0;
}
Look at this small code, you will understand. In C a string ended with a NULL character. We can use that advantage.
There are a few ways to do it. IMO, a simple, reasonable way to implement strlen is:
size_t string_length(const char *s) { return strchr(s, '\0') - s; }
but if you're not allowed to use strlen then you're probably not allowed to use strchr either. So you just have to count. The most idiomatic way to do that is probably a bit obscure for a complete beginner, so here is a more verbose method.
Note that your computation of the number of elements in the array is invalid, and has been corrected below.
#include <stdio.h>
int
length(const char *s)
{
int len = 0;
while( *s++ ){
len += 1;
}
return len;
}
int
main(void)
{
char *numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"
};
int count = sizeof numbers / sizeof *numbers; /* Number of entries */
for( int i = 0; i < count; i++ ){
printf(" length of %s is %d\n", numbers[i], length(numbers[i]));
}
return 0;
}
It's pretty subjective, but IMO a more idiomatic way to write this is:
#include <stdio.h>
int
length(const char *e)
{
const char *s = e;
while( *e++ )
;
return e - s - 1;
}
int
main(void)
{
char *numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"
};
char **e = numbers + sizeof numbers / sizeof *numbers;
for( char **t = numbers; t < e; t++ ){
printf(" length of %s is %d\n", *t, length(*t));
}
return 0;
}

Why does printing out an array of char result in random characters?

I am trying to learn programming and am doing some random questions and tasks. The task is to write out the last three characters of a string and this is what I've come up with. Please do not solve this for me, I am asking about my output/result not for anyone to do the problem solving for me:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int func(char *input_1, char *input_2) {
char last_three_digits_1[3]; // define two arrays that hold the last three characters
char last_three_digits_2[3];
int x = 0;
for(int y = strlen(input_1) - 4; y < strlen(input_1) - 1; y++) {
last_three_digits_1[x] = input_1[i];
x++;
}
x = 0; // repeat for the second string
for(int z = strlen(input_2) - 4; z < strlen(input_2) - 1; z++) {
last_three_digits_2[x] = input_2[i];
x++;
}
printf("last3_1: %s, \nlast3_2: %s\n", last_three1, last_three2); // this seem to access random memory because it outputs "abc" followed by random "-???" or "-????" or "-?2?2". Same for the second array.
return 0;
}
int main(int argc, char * argv[] ) {
if(argc == 3) { // needs to be two strings. E.g: "abcd efghi"
if(strlen(argv[1]) >= 3 || strlen(argv[2]) >= 3) { // if any of the strings are less than 3 in length, e.g. "ab wadnkwa" then do not proceed.
func(argv[1], argv[2]); // send the user input to the function
}
return 0; // maybe redundant
}
return 0; // return 0 for failure
}
The condition in the if statement
if(strlen(argv[1]) >= 3 || strlen(argv[2]) >= 3)
means that the length of one of the strings can be less than 3. In this case the function func can invoke undefined behavior.
It seems you mean
if(strlen(argv[1]) >= 3 && strlen(argv[2]) >= 3)
Otherwise you need in the function func to make a check whether a string has length greater than or equal to 3 before outputting its last three characters.
If a string has exactly three characters then for example in this loop
for(int i = strlen(text1) - 4; i < strlen(text1) - 1; i++)
the variable i can have an implementation defined value as for example -1 and as a result this expression text1[i] invokes undefined behavior.
The return type int of the function does not have a meaning.
Pay attention to that if you are using the format %s to output a character array using printf then the array shall contain a string that is a sequence of characters terminated with the zero character '\0'.
So neither the if statement in main nor the function itself makes a sense.
To output last three (or any other number) characters of a string there is no need to create an auxiliary array. It can be done much simpler.
For example
void func( const char *text1, const char *text2, size_t n )
{
size_t n1 = strlen( text1 );
if ( !( n1 < n ) ) text1 += n1 - n;
size_t n2 = strlen( text2 );
if ( !( n2 < n ) ) text2 += n2 - n;
printf( "last%zu_1: %s, \nlast%zu_2: %s\n", n, text1, n, text2 );
}
And the function can be called like
func( argv[1], argv[2], 3 );
Using such a declaration of the function you can output any number of last characters of two strings. Also take into account that the function parameters have the qualifier const because the passed strings are not changed within the function.
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
void func( const char *text1, const char *text2, size_t n )
{
size_t n1 = strlen( text1 );
if (!( n1 < n )) text1 += n1 - n;
size_t n2 = strlen( text2 );
if (!( n2 < n )) text2 += n2 - n;
printf( "last%zu_1: %s, \nlast%zu_2: %s\n", n, text1, n, text2 );
}
int main( void )
{
func( "Hello", "World", 3 );
}
The program output is
last3_1: llo,
last3_2: rld
char last_three1[3]; // define two arrays that hold the last three characters
char last_three2[3];
You need space to hold \0 char, because %s expects char* to be \0 terminated.
char last_three1[4];
char last_three2[4];
….
last_three1[x] = '\0';
x = 0; // repeat for the second string
for(int i = strlen(text2) - 4; i < strlen(text2) - 1; i++) {
last_three2[x] = text2[i];
x++;
}
last_three2[x] = '\0';
Strings in C are terminated with a single zero byte.
You're not zero-terminating the strings, so printf doesn't know where to stop printing (and you're lucky your program doesn't outright crash).
I'd refactor things like this, so you have a single function that simply copies the three last bytes and zero-terminates the string:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// out must be an array that can hold 4 bytes
// in must be >= 3 characters; otherwise this function returns non-zero
int get_last_three(char *out, const char *in) {
int len = strlen(in);
if (len < 3)
return -1;
for (int i = len - 3; i < len; i++) {
*out = in[i];
out++;
}
*out = 0; // Zero-terminate
return 0;
}
int main(int argc, char *argv[]) {
char out[4];
for (int i = 1; i < argc; i++) {
if (get_last_three(out, argv[i]) == 0) {
printf("last3_%d: %s\n", i, out);
}
}
}

Getting garbage after reversing string in c

I am trying to reverse a string. scanf is working well but when I use fixed string then it gives garbage value. So where is the fault ?
#include<stdio.h>
#include<string.h>
int main()
{
char s[50]="Hi I Love Programming";
char rev[strlen(s)];
int i,k;
k=strlen(s);
for(i=0; i<strlen(s); i++)
{
rev[k]=s[i];
k--;
}
printf("The reverse string is: %s\n", rev);
}
Your program has two issues:
1.
char rev[strlen(s)];
You forgot to add an element for the string-terminating null character '\0'.
Use:
char rev[strlen(s) + 1];
Furthermore you also forgot to append this character at the end of the reversed string.
Use:
size_t len = strlen(s);
rev[len] = '\0';
Note, my len is the k in your provided code. I use the identifier len because it is more obvious what the intention of that object is. You can use strlen(s) because the string has the same length, doesn´t matter if it is in proper or reversed direction.
2.
k=strlen(s);
for(i=0; i<strlen(s); i++)
{
rev[k]=s[i];
k--;
}
With rev[k] you accessing memory beyond the array rev, since index counting starts at 0, not 1. Thus, the behavior is undefined.
k needs to be strlen(s) - 1.
Three things to note:
The return value of strlen() is of type size_t, so an object of type size_t is appropriate to store the string length, not int.
It is more efficient to rather calculate the string length once, not at each condition test. Use a second object to store the string length and use this object in the condition of the for loop, like i < len2.
char s[50]="Hi I Love Programming"; can be simplified to char s[]="Hi I Love Programming"; - The compiler automatically detects the amount of elements needed to store the string + the terminating null character. This safes unnecessary memory space, but also ensures that the allocated space is sufficient to hold the string with the null character.
The code can also be simplified (Online example):
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "Hi I Love Programming";
size_t len = strlen(s);
char rev[len + 1];
size_t i,j;
for(i = 0, j = (len - 1); i < len; i++, j--)
{
rev[j] = s[i];
}
rev[len] = '\0';
printf("The reverse string is: %s\n", rev);
}
Output:
The reverse string is: pgnimmargorP evoL I iH
your program is hard to understand. Here you have something much simpler (if you want to reverse the string of course)
#include <stdio.h>
#include <string.h>
char *revstr(char *str)
{
char *start = str;
char *end;
if(str && *str)
{
end = str + strlen(str) - 1;
while(start < end)
{
char tmp = *end;
*end-- = *start;
*start++ = tmp;
}
}
return str;
}
int main()
{
char s[50]="Hi I Love Programming";
printf("%s", revstr(s));
}
https://godbolt.org/z/5KX3kP

How to read command-line arguments as integers instead of strings?

Sorry for my question, I know there are a lot similars but I didn't found any that is simple enaugh to help me.
I've started coding in C and try to solve a simple exercise: Read an integers array from command line, sum the elements using the function array_sum and print result. (input example array of 3 elements: 3 0 1 2)
int array_sum(int *array, size_t size);
int main(int argc, char **argv){
int sum=array_sum(argv, argc);
printf("array_sum: %i\n", sum);
return 0;
}
my problem is that argv is a char array and the function want an integer array.
Should I convert elements one by one in a new int array? There are better ways?
argv is an array of pointers to C strings. You need to convert the strings into integers first. You can do something like this:
int array_sum(int *array, size_t size);
int main(int argc, char **argv){
int *num_arr = malloc((argc - 1) * sizeof *num_arr);
for (int i = 0; i < argc - 1; ++i)
num_arr[i] = atoi(argv[i+1]);
int sum = array_sum(num_arr, argc - 1);
printf("array_sum: %i\n", sum);
free(num_arr);
return 0;
}
The only way to make the code in main shorter is by moving the conversion loop into a separate function that returns the malloced pointer.
In your code, char *argv[] is an array of char* pointers supplied from the command line. In order to convert the numbers supplied, you can use the following:
atoi(), which converts string arguement to an integer type.
Or strtol(), which converts the initial part of a string to a long int, given a base.
Other special functions from C99, alot of which are described in this post.
Since atoi() has no error checking, it is best to use strtol(), which allows extensive error checking.
You should store these converted numbers in a dynamically allocated int* pointer, which will need to be allocated on the heap using malloc(), which was suggested by #StoryTeller in his answer. You could also just declare an array on the stack, such as int arr[n]. The problem arises when you want to return this array in a function, which is not possible. Using a pointer in this case would allow more flexibility for abstraction.
malloc()allocates block of memory on the heap, and returns a void* pointer to it.
Note: malloc() should always be checked, as it can return NULL. You need to also free() this pointer at the end.
Here is some example code:
#include <stdio.h>
#include <stdlib.h>
#define BASE 10
/* Guessed that your function would look like this */
int array_sum(int *array, size_t size) {
int sum = 0;
for (size_t i = 0; i < size; i++) {
sum += array[i];
}
return sum;
}
int main(int argc, char *argv[]) {
int *arr = NULL;
char *endptr = NULL;
int check, sum;
size_t ndigits = (size_t)argc-1;
/* allocate pointer */
arr = malloc(ndigits * sizeof *arr);
if (arr == NULL) {
fprintf(stderr, "Cannot %zu spaces for integers\n", ndigits);
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < ndigits; i++) {
/* sufficient checking for strtol(), more can possibly be added here */
check = strtol(argv[i+1], &endptr, BASE);
if (endptr != argv[i+1] && *endptr == '\0') {
arr[i] = check;
}
}
sum = array_sum(arr, ndigits);
printf("array_sum: %d\n", sum);
/* pointer is free'd */
free(arr);
arr = NULL;
return 0;
}
Example input:
$ gcc -Wall -Wextra -std=c99 -o sumcommands sumcommmands.c
$ ./sumcommands 3 2 1
Output:
array_sum: 6
Note: You can use more error checking for strtol() on the Man page.
Why do you need to pass an int array as argument to the function ? No need to create an extra int array when you can simply do this :
int array_sum(char **argv, int argc){
int sum = 0;
for(int i = 0;i < argc - 1;i++){
sum += atoi(argv[i])
}
return sum;
}
You can use atoi() function to convert char ** array to **int . what i see here is each integer you type is converting into string rather than char.

Resources