#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char **wordlist=(char **)malloc(sizeof(char*)*4);
for(int i=0;i<4;i++)
{
char *word=(char*)malloc(sizeof(char*)*20);;
scanf("%s",word);
wordlist[i]=word;
free(word);
}
for(int i=0;i<4;i++)
{
printf("at %d value is %s\n",i,wordlist[i]);
}
free(wordlist);
return 0;
}
So the issue is as follows: I can run this code as many times as I want, and when it reads back the array I get COMPLETELY random results when it comes to where things are stored. Example: If input was "foo bar is great" it would output any combination of the following "value at 0 is bar value at 1 is bar value at 2 is great value at 3 is foo"
Part of a much larger program, but this is the concept i'm struggling to find a solution (or proper implementation) to. :( I have searched google high and low, as well as this site, with no solution that works properly. Any help is appreciated!
The program is wrong and has memory leaks.
For example in this statement
char *word=(char*)malloc(sizeof(char*)*20);;
^^^^^^^^^^^^^
there is used sizeof( char * ) instead of sizeof( char )
Then after these statements
wordlist[i]=word;
free(word);
wordlist[I] will point to memory that was deleted.
As result the program has undefined behavior.
What you need is something like the following
#include <stdio.h>
#include <stdlib.h>
#define N 4
#define M 20
int main( void )
{
char ( *wordlist )[M] = malloc( sizeof( char[N][M] ) );
for ( size_t i = 0; i < N; i++ )
{
scanf( "%19s", wordlist[i] );
}
for ( size_t i = 0; i < N; i++ )
{
printf( "at %zu value is %s\n", i, wordlist[i] );
}
free( wordlist );
return 0;
}
For example if to enter
one two free four
then the output will look like
at 0 value is one
at 1 value is two
at 2 value is free
at 3 value is four
Take into account that if your compiler supports variable length arrays then there is not necessary that the right-most dimension would be a constant.
Another approach is to allocate dynamically an array of pointers to first elements of one-dimensional character arrays.
For example
#include <stdio.h>
#include <stdlib.h>
#define N 4
#define M 20
int main( void )
{
char **wordlist = malloc( sizeof( char *[N] ) );
for ( size_t i = 0; i < N; i++ )
{
wordlist[i] = malloc( sizeof( char[M] ) );
scanf( "%19s", wordlist[i] );
}
for ( size_t i = 0; i < N; i++ )
{
printf( "at %zu value is %s\n", i, wordlist[i] );
}
for ( size_t i = 0; i < N; i++ ) free( wordlist[i] );
free( wordlist );
return 0;
}
The result will be the same as for the preceding program. However in this case instead to allocate only one two-dimensional array there are allocated several one-dimensional arrays.
You free each one of your words before actually printing it.
What you need to do is in the end(that is after the priniting -could be in the printing loop)
for (i=0;i<4;i++)
free(wordlist[i]);
free(wordlist)
and remove free(word); in the first loop
Related
I have a problem with the return of that function, it should return the vector with the typed sequence, but it's returning an ordered sequence, could you tell me where I'm going wrong?
Create a recursive function that takes a string as input and also its length. This function should return how many times the character the substring “hi” appears in the string.
Prohibited
The first line in the input contains the number n of test cases. Next, n lines occur, each containing a string of maximum length equal to 5000 characters
Exit
The output consists of n lines, each containing an integer that indicates the number of times the string “hi” occurs in the input string. All strings are written in lowercase letters.
Example
Prohibited
4
hipotenuse hipothermia hilux hifi
hi
hihihi
xavante hey
Exit
4
1
3
0
My code:
#include <stdio.h>
#include <string.h>
#define MAX 5000
int ocorrencias(const char *palavra, size_t len) {
char *st = "hi";
return len ?
(*st == *palavra) + ocorrencias(palavra + 1, len - 1) :
0;
}
int main() {
int n,i;
scanf("%d",&n);
char palavra[MAX];
int re[n];
for(i=0; i<=n; i++){
fgets(palavra, MAX, stdin);
re[i] = ocorrencias(palavra, strlen(palavra));
}
for(i=0; i<=n; i++){
printf("%d\n", re[i]);
}
}
For starters the for loops like this
for(i=0; i<=n; i++){
^^^^^
are wrong.
You need to write
for(i=0; i < n; i++){
^^^^^^
The function ocorrencias should be declared either like
size_t ocorrencias( const char *palavra );
or like
size_t ocorrencias( const char *palavra, const char *st );
instead of
int ocorrencias(const char *palavra, size_t len) ;
because it deals with strings and the function is able to determine lengths of passed strings.
It can be defined for example the following way
size_t ocorrencias( const char *palavra )
{
const char *st = "hi";
const char *p = strstr( palavra, st );
return p == NULL ? 0 : 1 + ocorrencias( p + strlen( st ) );
}
So in main you should write
size_t re[n];
//...
for ( i = 0; i < n; i++ )
{
printf( "%zu\n", re[i] );
}
Otherwise if you want to count substrings either "hi" or "hy" (according to your comment to the question) then the function can look the following way
size_t ocorrencias( const char *palavra )
{
const char *p = strchr( palavra, 'h' );
return p == NULL ? 0 : ( p[1] == 'i' || p[1] == 'y' ) + ocorrencias( p + 1 );
}
I'm trying to dynamically allocate memory for an array of strings, but I'm suffering a segmentation fault. If you can show me some ways to do it, that would be really helpful.
My knowledge so far is that char* is a string, and char** is a two-dimensional array of strings.
If s[i] is a string, shouldn't *(s + i) also be the same thing? I am confused about the topic.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int n;
int main(void)
{
scanf("%i", &n); //number of strings being inputted
char **s = calloc(n, 10 * (sizeof(char) + 1));
for (int i = 0; i < n; i++) //get strings
{
fgets(*(s + i), 10 * (sizeof(char) + 1), stdin);
}
for (int i = 0; i < n; i++) //print the strings
{
fputs(*(s + i), stdout);
}
return 0;
}
In this declaration
char **s = calloc(n, 10 * (sizeof(char) + 1));
you allocated a memory the address of which is assigned to the pointer s. The memory was zero-initialized due to calling the function calloc.
So in this statement
fgets(*(s + i), 10 * (sizeof(char) + 1), stdin);
the pointer s is dereferenced and either is a null pointer (because the pointed memory was zero-initialized) or has an indeterminate value if the expression s + i points outside the allocated memory.
You need to allocate an array of pointers of the type char * and assign to each pointer the address of an allocated array of characters.
Also in general you should check the return value of a call of calloc or malloc.
There is another problem with your code. After the call of scanf
scanf("%i", &n); //number of strings being inputted
the input buffer contains the new line character '\n' that will be read by the following call of fgets. So the first call of fgets will read in fact an empty string.
Another problem is that you should remove the new line character that can be appended to the read string by fgets. For example some read string can contain the new .line character while others can be without it depending on how many characters the user typed.
If you want to write the program without using the subscript operator with pointers then it can look for example the following way.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
size_t n = 0;
if ( scanf( "%zu", &n ) == 1 )
{
scanf( "%*[^\n]" );
scanf( "%*c" );
}
char **s = NULL;
if ( n != 0 ) s = calloc( n, sizeof( char * ) );
if ( s != NULL )
{
size_t len = 11;
size_t m = 0;
while ( m < n && ( *( s + m ) = malloc( len * sizeof( char ) ) ) != NULL ) m++;
size_t i = 0;
while ( i < m && fgets( *( s + i ), len, stdin ) != NULL ) i++;
m = i;
for ( i = 0; i < m; i++ ) //print the strings
{
( *( s + i ) )[ strcspn( *( s + i ), "\n" )] = '\0';
// or without the subscript operator
// *( *( s + i ) + strcspn( *( s + i ), "\n" ) ) = '\0';
puts( *( s + i ) );
}
for ( i = 0; i < n; i++ ) free( *( s + i ) );
}
free( s );
return 0;
}
The program output might look like
10
one
two
three
four
five
six
seven
eight
nine
ten
one
two
three
four
five
six
seven
eight
nine
ten
scanf("%i", &n); //number of strings being inputted
is incomplete, since scanf(3) can fail (e.g. if your user enters hello). You need to add more code checking that scanf was successful. I suggest:
if (scanf("%i", &n) < 0) {
perror("number of strings expected");
exit(EXIT_FAILURE);
}
Then
char **s = calloc(n, 10 * (sizeof(char) + 1));
is wrong. Each element of the array is a char*, which on most machines has 4 or 8 bytes (the sizeof(void*)).
So replace it with
char **s = calloc(n, sizeof(char*));
or with the equivalent char**s = calloc(n, sizeof(*s)); which in my opinion is less readable.
Also, calloc can fail. You need to add a test, like
if (s == NULL) {
perror("calloc of s");
exit(EXIT_FAILURE);
}
Read carefully the documentation of each function (like calloc, fgets etc...) which you did not wrote in this C reference.
The next step should be a loop filling each element of s. With another calloc, or some call to strdup(3) if your system provides it. Of course, that calloc (or strdup) can also fail and you need to test against failure.
You could also use getline(3) (or even readline(3)) if your system has it. Check with your manager if you are legally and technically allowed to use them.
If your compiler is GCC, invoke it with all warnings and debug info: gcc -Wall -Wextra -g. Once you have no warnings, use a debugger like GDB to understand the behavior of your executable.
Consider also using the Clang static analyzer (after getting permission to use it).
Draw on board (or on paper) a figure with arrows representing pointers (like the doubly linked-list figure on wikipedia) to understand the behavior of your program.
I've been doing this code wars challenge in which you have to take a string, and capitalize each letter, forming a Mexican wave-looking array of strings. For example, an input string like
hello
will result in ["Hello", "hEllo", "heLlo", "helLo", "hellO"]
I managed to complete it in JavaScript, and decided to attempt it in C. The actual code itself is working, as it prints the correct output, but the problem I am having is actually storing the string inside a double pointer.
This is my code:
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void wave(char *s, char **array);
int main(void)
{
char *s = malloc(6);
strcpy(s, "hello");
char **array = malloc(pow(strlen(s)+1, 2));
wave(s, array);
for (int i = 0; i < strlen(s); i++)
{
printf("s = %s\n", array[i]);
}
free(array);
free(s);
return 0;
}
void wave(char *s, char **array)
{
char s2[strlen(s)+1];
for (int i = 0; i < strlen(s); i++)
{
s[i] = tolower(s[i]);
}
int array_index = 0;
for (int i = 0; i < strlen(s); i++)
{
strcpy(s2, s);
if (s[i] != ' ')
{
s2[i] = toupper(s2[i]); // Printing out `s2` here results in the correct output
array[array_index++] = s2; // Adding it here works, but when trying to access it outside of this function, it gives the incorrect output
}
}
}
When printing the string inside the function, I get the following output (which is correct):
Hello
hEllo
heLlo
helLo
hellO
But when I try to print it out inside the main() function, I get the following:
s = hellO
s = hellO
s = hellO
s = hellO
s = hellO
It seems like it is adding/accessing only the last string in the array. I cannot understand why accessing the element inside the wave() function works, but accessing it outside of that function doesn't.
I've had this problem twice before, both in C and C++, and have been unable to solve it, and it is really annoying me.
I left this as a comment, but since it might not be clear, I'll post my answer in code...
As stated in my comment, there's no point allocating a pointer array - on a 64 bit machine, that would be 6 pointers, each requiring 8 bytes to point at a 7 byte long data block - a total of 104 bytes (ignoring the added allocator padding per allocation).
Instead, a single allocation could suffice, allocating 42 bytes to contain all the "wave" strings and their NUL byte in a single block of memory (saving memory while improving locality).
int main(void) {
/* Assuming string "hello" */
const char *org = "hello";
/* Calculate length only once and store value */
const size_t len = strlen(org);
const size_t len_with_nul = len + 1;
/* Allocate `len` strings in a single allocation */
char *buf = malloc(len * len_with_nul);
/* Copy each string to it's place in the buffer */
for (size_t i = 0; i < len; ++i) {
/* position in the buffer */
char *pos = buf + (i * len_with_nul);
/* copy the NUL as well */
memcpy(pos, org, len_with_nul);
/* Wave... */
pos[i] = toupper(pos[i]);
}
/* Print result */
for (size_t i = 0; i < len; i++) {
char *pos = buf + (i * len_with_nul);
printf("s = %s\n", pos);
}
/* Free buffer */
free(buf);
return 0;
}
EDIT - Why is using a single memory block better?:
In this case we allocate a single memory "block" (blob / slice). This offers a number of advantages:
We perform a single allocation and deallocation instead of a larger number of allocations and deallocations.
This improves speed by performing less actions.
We also improve memory locality, which minimizes CPU cache misses and improves performance.
We use less memory.
Each memory allocation comes with a price - we need a pointer to hold the memory address for the memory we allocated. A pointer "costs" 8 bytes on a 64bit machine and 4 bytes on a 32bit machine.
By using a single allocation, we "pay" less.
This is true even if we ignore the metadata attached to the memory block allocated (which requires memory from the memory allocator).
I should note that C doesn't really care about the contents of a memory block, it's all zeros and ones. The meaning given to these zeros and ones is left to the developer.
Even the printf function doesn't care about the contents of the memory it's reading - it simply reads the memory according to the formatting it was instructed to follow by the developer (the %s informs the function that the memory relates to a NUL terminated string).
There are some concerns about memory alignment which are CPU and system specific - but these don't apply to single byte strings. They apply to multi-byte types (such as short, int, and long). So we don't need to worry about them in this example.
In this sense, it basically means that the developer is free to manage the memory and the contents as they see fit (putting aside memory alignment).
This is not to say that it's always better to allocate a single block of memory (if you need to use realloc, you might prefer smaller chunks)... but usually a single block of memory is better.
For starters it is unclear why you are allocating dynamically memory for the string literal "hello".
char *s = malloc(6);
strcpy(s, "hello");
It does not make any sense.
Just write
const char *s = "hello";
This declaration
char **array = malloc(pow(strlen(s), 2));
also does not make sense. What you need is the following.
size_t n = strlen( s );
char **array = malloc( n * sizeof( char * ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = malloc( n + 1 );
}
The function wave can be defined the following way
void wave( const char *s, char **array )
{
size_t n = strlen( s );
for ( size_t i = 0; i < n; i++ )
{
strcpy( array[i], s );
array[i][i] = toupper( ( unsigned char )s[i] );
}
}
and then in main after the function call
for ( size_t i = 0; i < n; i++ )
{
puts( array[i] );
}
for ( size_t i = 0; i < n; i++ ) free( array[i] );
free( array );
Here is the full program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void wave( const char *s, char **array )
{
size_t n = strlen( s );
for ( size_t i = 0; i < n; i++ )
{
strcpy( array[i], s );
array[i][i] = toupper( ( unsigned char )s[i] );
}
}
int main(void)
{
const char *s = "hello";
size_t n = strlen( s );
char **array = malloc( n * sizeof( char * ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = malloc( n + 1 );
}
wave( s, array );
for ( size_t i = 0; i < n; i++ )
{
puts( array[i] );
}
for ( size_t i = 0; i < n; i++ ) free( array[i] );
free( array );
return 0;
}
Its output is
Hello
hEllo
heLlo
helLo
hellO
#include <stdio.h>
main()
{
int num[9], i = 0, count = 0;
while (i<10)
{
scanf("%d", &num[i]);
if (num[i] % 2 == 0)
{
count++;
}
i++;
}
printf("we have %d double numbers\n", count);
}
Run-Time Check Failure #2 - Stack around the variable was corrupted
What should I do?
Your while loop hits all values of i from 0 to 9 inclusive, but attempting to access num[9] takes you out of bounds. You'll need to reduce the while loop range:
while (i<9) {
...
}
In addition, you really should give your main() function a return type, since modern compilers don't tolerate it being missing:
int main()
{
...
return 0;
}
The valid range of indices that can be used to access an array with N elements is [0, N - 1] or that is the same [0, N ).
Thus the condition in the while statement
while (i<10)
has to be rewritten like
while (i < 9)
The reason of the error is using "magic numbers" throughout the program.
Try to use named constants instead of magic numbers, In this case it will be easy to understand what magic number is used in what part of the code.
The program can look like
#include <stdio.h>
#define N 9
int main( void )
{
int num[N];
unsigned int count = 0;
unsigned int i = 0;
while ( i < N )
{
scanf( "%d", &num[i] );
if ( num[i] % 2 == 0 ) ++count;
i++;
}
printf( "we have %u double numbers\n", count);
}
Instead of the while loop it would be better to use a for-loop because the variable i is not used outside the loop.
For example
#include <stdio.h>
#define N 9
int main( void )
{
int num[N];
unsigned int count = 0;
for ( unsigned int i = 0; i < N; i++ )
{
scanf( "%d", &num[i] );
if ( num[i] % 2 == 0 ) ++count;
}
printf( "we have %u double numbers\n", count);
}
A more correct approach of declaring indices of arrays is using the type size_t for them.
In fact the array is not used in the program. You could count even entered values without using an array.
Take into account that according to the C Standard the function main without parameters shall be declared like
int main( void )
Is there a way in C to assign strings with integers.
I have a 2d array of strings and I know its already assigned with indexes but I want to assign each with a random number like an id.
I don't know if I should do this after submitting it into an array or when I am reading messages directly.
I would like to have something like this
2d array:
john
michael
simon
What I want:
john - 234
michael - 432
simon - 489
My function code to insert names into an array
int store(char *stock){
int r;
static char test[5][10];
static int i=0;
int k,j=0;
//this just copies names from another function
strcpy(test[i], stock);
printf("%s in index:%d\n",test[i],i);
qsort(test, i, 10, cmp);
if (i==4)
{
for (j = 0; j < 5; j++) {
printf("%s\n",test[j]);
}
}
i++;
}
thanks
You should use snprintf(3) (avoid the old sprintf because of possible buffer overflows). On GNU systems, you could use asprintf(3) which heap allocates a string (see also strdup(3) which duplicates an existing string).
You have to convert an integer to the string representation in C.
Use ltoa()/itoa()/_itoa_s() or sprintf()/snprintf()
Secondly, if its a buffer and not a pointer, then you can't assign to it, you have to copy into it.
NOTE:
Be aware of buffer overruns, prefer the safe versions of all functions. The safe way to use sprintf() if your platform lacks snprintf() or _itoa_s() is to (1) avoid unbounded format strings (%s, etc.) and (2) recognize what you are formatting, and its max bounds.
Example, for a 64-bit integer:
Max value:
18,446,744,073,709,551,615
The base 10 ASCII length of this would be 20 characters. Use an order of magnitude larger for a character buffer. I like to use a 1024 length buffer for sprintf() conversions.
18446744073709551615 (unsigned) will be approx 20 length.
char buf[1024];
int64_t lval;
sprintf(buf, "%d", lval);
return strdup(buf); // then dup it, or use strlen to malloc heap mem for your copy
Here is an example of how it can be done
#include <stdio.h>
#include <string.h>
#define N 3
#define M 15
int main( void )
{
static char test[N][M] = { "john", "michael", "simon" };
unsigned int a[N] = { 234, 432, 489 };
size_t i;
for ( i = 0; i < N; i++ )
{
sprintf( test[i] + strlen( test[i] ), " - %u", a[i] );
}
for ( i = 0; i < N; i++ )
{
puts( test[i] );
}
return 0;
}
The output is
john - 234
michael - 432
simon - 489
Instead of sprintf you may use snprintf if your compiler supports it. For example
#include <stdio.h>
#include <string.h>
#define N 3
#define M 15
int main( void )
{
static char test[N][M] = { "john", "michael", "simon" };
unsigned int a[N] = { 234, 432, 489 };
size_t i;
for ( i = 0; i < N; i++ )
{
size_t n = strlen( test[i] );
snprintf( test[i] + n, M - n, " - %u", a[i] );
}
for ( i = 0; i < N; i++ )
{
puts( test[i] );
}
return 0;
}