I have written a code which creates multiple random strings. But every time I print it, only the last string is printed multiple times even though different strings are created every time. Can anyone tell me what I'm doing wrong.
static const char alphanum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz";
char s[5],*b[5] ;
int num =0;
for(int j=0;j<5;j++)
{
*b=(char*)malloc(sizeof(char*)*10);
for (int i = 0; i < 4; ++i)
{
num = rand() % (sizeof(alphanum) - 1);
s[i] = alphanum[num];
}
s[4] = 0;
printf("%s\t",s);
b[j] = s;
}
for(int j=0;j<5;j++)
printf("\n%s",b[j]);
}
Assuming that you've seeded the random number generator with, for instance, srand(time(NULL));, so that it will generate different random number sequences on each run of the program, there is one more flaw in your code:
s is a pointer to an array of characters. With the assignment b[j] = s;, you only assign b[j] the pointer (memory location) of s, but not the contents of s. Since the memory location of s does not change, all entries of b contain the same reference to the same string s, which has been changed multiple times. To copy the current content of s to b[j], use strcpy(), like this.
strcpy(b[j], s);
I think your should read the man 3 rand
In facts you have to "seed" your rand by calling void srand(unsigned int seed); one time in the beggining of your application
First of all, doing e.g. *b is the same as *(b + 0) which is the same as b[0]. That means that when you allocate memory you assign it to the same entry all the time.
Secondly, last in the loop you overwrite the pointer and make b[j] point to s, all the time. So all pointers in b will point to the same s. That's why all your strings seems to be the same.
Thirdly, you don't need to allocate dynamically in the loop, as all strings are of a fixed size. Instead declare b as an array of arrays of characters:
char b[5][5];
Then instead of assigning the pointer, you copy the string into the correct entry in b.
Lastly, and for future reference, don't cast the return of malloc.
Related
I just started learning C language and I need some help with a program. Here is the code.
Questions:
What is this? customerData[NUM_FIELDS][FIELD_LENGTH];
Is it a char 2D array?
How do you input data into the array? fgetC, putchar, getchar ?
#include <stdio.h> #include <string.h> #include <stdlib.h>
#define INPUT_LENGTH 128
#define FIELD_LENGTH 30
#define NUM_FIELDS 9
int main()
{
FILE *data=NULL;
char input[INPUT_LENGTH];
char customerData[NUM_FIELDS][FIELD_LENGTH];
int element=0;
char *next;
char ch;
data= fopen("data.txt","r");
if(data!=NULL)
{
//token=strtok(input,"|");
/*while loop will go through line by line and stored it in an input array*/
while(fgets(input,INPUT_LENGTH,data)!= NULL)
{
next=strtok(input,"|");
while(next!=NULL)
{
//ch=getchar()
//>probably a get char for ch
strcpy(next,customerData[element][strlen(next)]);
/*need to put the values into customer data one by one*/
printf("%s\n",next);
//element+=1;
next=strtok(NULL,"|");
}
//element=0;
}
printf("program is done\n");
}
fclose(data);
return 0;
}
In general, "help me with my code" questions are off-topic on Stack Overflow. In order to keep the question on-topic, I'm going to focus only on the question of how to access 2D char arrays.
Yes, this is a 2D char array. Or, put another way, it's an array with NUM_FIELDS elements, where each element of the array is a char array with FIELD_LENGTH elements.
There are loads of ways to insert data into a 2D char array, but there are probably two I've encountered most often. Which one you choose to use will depend on how you want to think of this array.
Option 1: A 2D array of single chars
The first way to think about this variable is simply as a 2D array of chars - a grid of elements that you can access. Here, you can simply input values using the normal assignment operator. You'll want to make sure that your indexes are in range, or you'll start accessing invalid memory.
//Set a known element that's definitely in range
customerData[1][2] = 'A';
//Loop through all the elements
for(int ii = 0; ii < NUM_FIELDS; ii++)
{
for (int jj = 0; jj < FIELD_LENGTH; jj++)
{
customerData[i][j] = 'B';
}
}
//Set an element from variables
char nextInput = getNextCharFromInput();
if(x < NUM_FIELD && y < FIELD_LENGTH)
{
customerData[x][y] = nextInput;
}
//Bad. This could corrupt memory
customerData[100][60] = 'X';
//Risky without check. How do you know x and y are in range?
cusomterData[x][y] = 'X';
You could certainly write your code by assigning these elements on character at a time. However, the broader context of your program heavily implies to me that the next option is better.
Option 2: A 1D array of fixed-length strings
In C, a "string" is simply an array of chars. So another way to look at this variable (and the one that makes the most sense for this program) is to treat it as a 1D array of length NUM_FIELDS, where each element is a string of length FIELD_LENGTH.
Looking at this this way, you can start using the C string functions to input data into the array, rather than needing to deal character by character. As before, you still need to be careful of lengths so that you don't go off the end of the strings.
Also be aware that all array decay into pointers, so char* is also a string (just of unknown length).
//Set a specific field to a known string, which is short enough to fit
strcpy(customerData[2], "date");
//Loop through all fields and wipe their data
for(int ii = 0; ii < NUM_FIELDS; ii++)
{
memset(customerData[ii], 0, FIELD_LENGTH);
}
//Set field based on variables
if(x < NUM_FIELDS)
{
//Will truncate next if it is too long
strncpy(customerData[x], next, FIELD_LENGTH);
//Will not input anything if field is too long
if(strlen(next) < FIELD_LENGTH)
{
strcpy(customerData[x], next);
}
}
//Bad. Could corrupt memory
strcpy(customerData[100], "date");
strcpy(customerData[1], "this string is definitely much longer than FIELD_LENGTH");
//Risky. Without a check, how do you know either variable in in range?
strcpy(customerData[x], next);
getchar and fgetC both deal with reading characters, from stdout and a file respectively, so can't be used to put data into a variable. putchar does deal with put character into things, but only stdout, so can't be used here.
I really don't know how to implement this function:
The function should take a pointer to an integer, a pointer to an array of strings, and a string for processing. The function should write to array all variations of exchange 'ch' combination to '#' symbol and change the integer to the size of this array. Here is an example of processing:
choker => {"choker","#oker"}
chocho => {"chocho","#ocho","cho#o","#o#o"}
chachacha => {"chachacha","#achacha","cha#acha","chacha#a","#a#acha","cha#a#a","#acha#a","#a#a#a"}
I am writing this in C standard 99. So this is sketch:
int n;
char **arr;
char *string = "chacha";
func(&n,&arr,string);
And function sketch:
int func(int *n,char ***arr, char *string) {
}
So I think I need to create another function, which counts the number of 'ch' combinations and allocates memory for this one. I'll be glad to hear any ideas about this algorithm.
You can count the number of combinations pretty easily:
char * tmp = string;
int i;
for(i = 0; *tmp != '\0'; i++){
if(!(tmp = strstr(tmp, "ch")))
break;
tmp += 2; // Skip past the 2 characters "ch"
}
// i contains the number of times ch appears in the string.
int num_combinations = 1 << i;
// num_combinations contains the number of combinations. Since this is 2 to the power of the number of occurrences of "ch"
First, I'd create a helper function, e.g. countChs that would just iterate over the string and return the number of 'ch'-s. That should be easy, as no string overlapping is involved.
When you have the number of occurences, you need to allocate space for 2^count strings, with each string (apart from the original one) of length strlen(original) - 1. You also alter your n variable to be equal to that 2^count.
After you have your space allocated, just iterate over all indices in your new table and fill them with copies of the original string (strcpy() or strncpy() to copy), then replace 'ch' with '#' in them (there are loads of ready snippets online, just look for "C string replace").
Finally make your arr pointer point to the new table. Be careful though - if it pointed to some other data before, you should think about freeing it or you'll end up having memory leaks.
If you would like to have all variations of replaced string, array size will have 2^n elements. Where n - number of "ch" substrings. So, calculating this will be:
int i = 0;
int n = 0;
while(string[i] != '\0')
{
if(string[i] == 'c' && string[i + 1] == 'h')
n++;
i++;
}
Then we can use binary representation of number. Let's note that incrementing integer from 0 to 2^n, the binary representation of i-th number will tell us, which "ch" occurrence to change. So:
for(long long unsigned int i = 0; i < (1 << n); i++)
{
long long unsigned int number = i;
int k = 0;
while(number > 0)
{
if(number % 2 == 1)
// Replace k-th occurence of "ch"
number /= 2;
k++;
}
// Add replaced string to array
}
This code check every bit in binary representation of number and changes k-th occurrence if k-th bit is 1. Changing k-th "ch" is pretty easy, and I leave it for you.
This code is useful only for 64 or less occurrences, because unsigned long long int can hold only 2^64 values.
There are two sub-problems that you need to solve for your original problem:
allocating space for the array of variations
calculating the variations
For the first problem, you need to find the mathematical function f that takes the number of "ch" occurrences in the input string and returns the number of total variations.
Based on your examples: f(1) = 1, f(2) = 4 and f(3) = 8. This should give you a good idea of where to start, but it is important to prove that your function is correct. Induction is a good way to make that proof.
Since your replace process ensures that the results have either the same of a lower length than the original you can allocate space for each individual result equal to the length of original.
As for the second problem, the simplest way is to use recursion, like in the example provided by nightlytrails.
You'll need another function which take the array you allocated for the results, a count of results, the current state of the string and an index in the current string.
When called, if there are no further occurrences of "ch" beyond the index then you save the result in the array at position count and increment count (so the next time you don't overwrite the previous result).
If there are any "ch" beyond index then call this function twice (the recurrence part). One of the calls uses a copy of the current string and only increments the index to just beyond the "ch". The other call uses a copy of the current string with the "ch" replaced by "#" and increments the index to beyond the "#".
Make sure there are no memory leaks. No malloc without a matching free.
After you make this solution work you might notice that it plays loose with memory. It is using more than it should. Improving the algorithm is an exercise for the reader.
I am trying to count the number of elements in an array using C. I tried out the following code. But it just returns 83 every time I run the program. What I mean by to count the number of elements is that I need to know the number of elements that we have entered and not the size of the array.
#include<stdio.h>
#include<stdlib.h>
main(){
int a[100], j = 0, i;
a[0] = '0';
a[1] = '1';
a[2] = '2';
a[3] = '3';
a[4] = '4';
a[5] = '5';
for(i=0; i<100; i++){
if(a[i] == '\0'){
}
else
j = j + 1;
}
printf("%d", j);
system("pause");
}
Arrays in C are a fixed size. They do not expand. Your array has two entries; writing to array[2], array[3], etc. invokes undefined behaviour. In other words, it's invalid code.
If you want to be able to insert an arbitrary number of elements, you will need to use dynamically-allocated memory, manually track how many elements you've inserted, and use realloc when you need to resize.
Since the OP amended his code, here is a more correct reply:
This code works 'by chance', since you didn't initialize the array previously.
It's just 'luck', that somewhere in there, the value 0 comes up.
The declaration of an array does NOT zero it.
Use:
memset(a, 0, 100);
For that. That way, the first 'not overwritten' byte will return '0'.
Reference: http://www.cplusplus.com/reference/clibrary/cstring/memset/
Alternatively, you have to set the 'delimited' manually by adding a[x] = 0;
Now, I know you specifically asked for a 'C' solution, but if you would like to consider using a C++-Compiler, I suggest looking at the stl of C++.
Here's a link to get you started: http://www.cplusplus.com/reference/stl/list/
It's initialized as:
list<char>List;
List.push_back(1);
List.push_back(2);
List.push_back('a');
int j = List.size(); //Returns '3'
do this instead:
main(){
int a[100] = {0};
int j = 0;
int i = 0;
// other stuff
Update based on new code:
In general, you will need a way to identify the end of your array in order to do a correct count. For strings the '\0' is used generally. For other data types you have to come up with your own value to check.
For your specific code example above:
You need to insert a \0 yourself into your array in the last position so that your count will work. (When you create a string like "hello", the '\0' gets automatically put in for you at the end of the string, but not if you create a string character by character).
Alternatively, check for the character '5' to find the end of your current array of characters.
Also, you should break out of the loop once you found the last character, otherwise you are going past the end of the array and will most likely crash (again, if you don't it's sheer luck). I.e., something like:
if(a[i] == '\0'){
break;
}
will work if you do:
a[6] = '\0';
before.
Since C doesn't check array bounds, it might appear that with your current code you seemingly get away with this, but it's sheer luck that the program doesn't crash and may change from run to run. In other words, this is undefined behavior.
Finally, you can of course also use strlen() if you are dealing with strings.
I am trying to find all of the numbers that are repeated across two arrays..
For example:
array1[2]: 1,2
array2[2]: 1,5
The number that repeats itself is 1 so we create a new array that will contain 1.
array3[2]: 1
My code is:
int func1(int *str, int *str2)
{
int i,j,temp,c[10];
for(i=0;i<*(str+i);i++){
for(j=0;j<*(str2+j);j++){
if(*(str+i) == *(str+j))
{
temp = *(str+i);
*(str+i) = temp;
temp = *(c+i);
return c[i];
}
}
}
return 0;
}
What is the problem?(logically)
Thanks.
There are multiple problems:
The conditions in the two for loops are odd and probably wrong. They are equivalent to:
for (i = 0; i < str1[i]; i++)
for (j = 0; j < str2[j]; j++)
You should probably specify the sizes of the input arrays in the function interface.
In C, you must make sure you always know the sizes of the arrays.
You should probably specify the output array in the function interface.
Since you will need to know how many values were found in common, you'll need to return that number from the function.
Your choice of the names str1 and str2 is unusual. Not technically wrong, but probably not a good idea. Such names should be reserved for character strings, not arrays of integers.
Your local array c is barely used, and is not used safely.
Your code returns when it finds the first pair of numbers that match, not all possible matches.
The first two lines of the body of the if statement elaborately copies the value in str[i] back to itself via temp.
The third line of the body of the if statement copies an uninitialized value from array c into the variable temp.
The last line of the body of the if then returns that uninitialized value.
This adds up to changes such as:
int func1(int *arr1, int num1, int *arr2, int num2, int *arr3)
{
int k = 0;
for (int i = 0; i < num1; i++)
{
for (int j = 0; j < num2; j++)
{
if (arr1[i] == arr2[j])
arr3[k++] = arr1[i];
}
}
return k;
}
Note that this code assumes that the size of arr3 (the array, not the pointer itself) is as big as the product of num1 and num2. If both arrays contain a list of the same value, then there will be one row in the output array, arr3, for each pair so it could use num1 * num2 rows. This points out that the code does not deal with suppressing duplicates; if you need that (you likely do), then the body of the if statement needs to search through the current values in arr3 to check that the new value is not present. It would be wise to add another parameter, int siz3, to indicate the size of the third array; if you run out of space for values, you could then return -1 as an error indication.
The coded algorithm is quadratic (or, more accurately, proportional to the product num1 * num2). If you know the arrays are sorted on entry, you can reduce it to a linear algorithm (proportional to num1 + num2). With duplicate elimination, it is a little more expensive - it isn't quite as simple as 'cubic'. If you know the input arrays contain unique values (no duplicates), then duplicate elimination is obviously not necessary.
for(i=0;i<*(str+i);i++){
for(j=0;j<*(str2+j);j++){
Are wrong. You are applying '<' condition on an integer to itself and hence loop condition breaks. So, the loop never runs.
And why are you using these redundant statements?
temp = *(str+i);
*(str+i) = temp;
Also, this is wrong
temp = *(c+i);
return c[i];
Try more to correct those statements.If you can't do again, I will provide you a solution
I got the following problem:
I have an array of char pointers
char *opts[] = { "-a", "--append", "-b" };
and a command name stored in
char cmd[] = "ls";
Now I need to compute all possible combinations, which I've done using the GNU Scientific Library and execute the command with the compute combinations.
The problem I have is how to compute the amount of memory I need for the char * getting passed to system().
Here's my first try:
int length = strlen(cmd) * sizeof(char);
for (int i = 0; i < 3; ++i) {
length += strlen(opts[i]) * sizeof(char);
}
Well, it worked, but I sense that this is not the right/best solution. Can't I cast the two-dimensional-array to a flat one-dimensional-array and get the size of it (if I'm not wrong, the are no multidimensional arrays in C, C only mimics them).
Can't I cast the two-dimensional-array to a flat one-dimensional-array
Technically not true, but irrelevant here, as you do not have a two-dimensional array. You have a 1-dimensional array of values which happen to have a length. There is no guarentee that those strings are in contiguous memory, so it would be impossible to measure their total sizze in one step.
The way to have it is the only way to get th evalue you want.
P.S. Note that sizeof(char) is guaranteed to equal 1.
P.P.S While I've already marked-down tommie75's answer, we can put part of it to use:
int numelem = sizeof(opts) / sizeof(opts[0]);
for (int i = 0; i < numelum; ++i)
{
length += strlen(opts[i]) * sizeof(char);
}