Related
I've created a function to reverse an array in C. The first run of the function will reverse the array perfectly. Runs following that will fill the first and/or last index of the array with seemingly random info. I'm assuming this may have to do with the array accidentally receiving information from surrounding memory addresses after several runs.
My function is written as follows:
void reverse_array(int array[], int* result, int size) {
int index = 0;
int reverse_index;
for (reverse_index = size - 1; reverse_index > 0; reverse_index--) {
result[index] = array[reverse_index];
index++;
}
}
Running the following code with "nums" being an array filled with integers 0 to 99, the expected output is returned:
int main(void) {
int size = 100;
int nums[size];
int i;
for (i = 0; i < size; i++) {
nums[i] = i;
}
int reversed[size];
reverse_array(nums, reversed, size);
print_array(reversed);
return 0;
}
The problem arises when I try and run the function several times consecutively. In the following code, I attempt to flip an array several times:
int main(void) {
int size = 100;
int nums[size];
int i;
for (i = 0; i < size; i++) {
nums[i] = i;
}
int reversed[size];
reverse_array(nums, reversed, size);
int reversed2[size];
reverse_array(reversed, reversed2, size);
int reversed3[size];
reverse_array(reversed2, reversed3, size);
int reversed4[size];
reverse_array(reversed3, reversed4, size);
int reversed5[size];
reverse_array(reversed4, reversed5, size);
print_array(reversed5, size);
return 0;
}
Printing out the second flip, or "reversed2," returns the following:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 32760,
The output is almost exactly as to be expected, except for the final index. This happens with all following flips, though with different values. Printing the 5th flip, or "reversed5," yields the following:
0, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80,
79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60,
59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40,
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20,
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 32760,
I'm very new to C, and can only guess what is causing this. As stated above, I think it may have to do with the array accidentally picking up information from surrounding memory addresses, but that's only a guess. Thanks for reading, any help is greatly appreciated.
Edit: Thank you all very much. I could not ask for more straight forward and helpful responses. I feel kind of dumb now, but that's part of the learning process.
for (reverse_index = size - 1; reverse_index > 0; reverse_index--)
Your problem is with this line of code,this > should be changed to >=.
This is my function:
char** split_string(char* message){
int i = 0;
int j = 0;
int numberOfMsgs = 0;
int charsInLastMsg = (int)(strlen(message)%140);
if((int)strlen(message) > 140*4){
return NULL;
}
if((int)(strlen(message)%140)){
numberOfMsgs = (int)(strlen(message)/140) + 1;
}
else{
numberOfMsgs = (int)(strlen(message)/140);
}
printf("message length = %d, we will have %d messages, and last msg will have %d characters\n", (int)strlen(message), numberOfMsgs, charsInLastMsg);
char **m = malloc(numberOfMsgs * sizeof(char*));
for (j =0 ; j <= numberOfMsgs; j++){
m[j] = malloc(141 * sizeof(char));
}
for(i=0;i<numberOfMsgs;i++){
if(i == numberOfMsgs - 1){
memcpy(m[i], message + (140*i), charsInLastMsg);
m[i][charsInLastMsg] = '\0';
}
else{
memcpy(m[i], message + (140*i), 140);
m[i][140] = '\0';
}
printf("m%d = %s\n", i, m[i]);
}
return m;
}
Which I'm calling like this:
char* message = "1, 2, 3, 4, 5, 6, 7, 8, 9 and 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100.";
int i=0;
char** m = split_string(message);
while(*m){
printf("string%d = %s\n", i, m[i]); //Problem at this line.
m++;
}
But, when I run it, I'm getting a segmentation fault at the line indicated above. If I don't print, the program runs fine, so I think the function split_string() is alright.
What am I doing wrong? I'm a newbie, plz help.
/************************************EXPECTED O/P**********************************/
I want the string to be split into 140 char strings as below:
string0 = 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36
string1 = , 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71
string2 = , 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100.
There are several issues in your code. You have already fixed some.
Your client code
while (*m) {
printf("string%d = %s\n", i, *m);
i++;
m++;
}
(where I have taken the liberty to replace m[i] with i always 0 with *m) suggests that the char-pointer array m is NULL-terminated, i.e. that a NULL pointer indicates the end of the string list. (Much like a '\0' character indicates the end of a string.)
But your function split_string doesn't put a NULL pointer at the end: Your client code will read beyond valid memory.
char **m = malloc(numberOfMsgs * sizeof(char*));
Here, you should allocate (numberOfMsgs + 1) strings, one extra for the NULL.
for (j =0 ; j <= numberOfMsgs; j++){
m[j] = malloc(141 * sizeof(char));
}
Here, you should only allocate numberOfMsgs strings. The NULL string doesn't have to be allocated, just be set to NULL:
m[numberOfMsgs] = NULL;
Finally, you should free the allocated memory. In your case, you can't do that, because you have incremented (and thus changed) the base pointer m. The OS can't free the memory, because the new m isn't registered by the memory allocator.
So, for example:
char **m = split_string(message, 140);
int i = 0;
while (m[i]) {
printf("%d: '%s'\n", i, m[i]);
free(m[i]);
i++;
}
free(m);
That is the problem working with arrays, the information about its size should be stored somewhere, you can never know looking at a char ** how many members it has.
That is why null-terminated strings (c strings) exist, the NULL char marks its end, so you have to iterate through the whole string until you find NULL to know it's length.
Anyway, I´d suggest you modify your split_string() function to:
char** split_string(char* message, size_t * n_msgs) {
//...
*n_msgs = numberOfMsgs;
///
}
And then:
size_t msgs = 0;
char** m = split_string(message, &msgs);
//...
Your while loop is an infinite loop. You are testing the expression *m which never changes, so you will keep increasing i and eventually m[i] will refer to memory that has not been allocated.
You should change for (j =0 ; j <= numberOfMsgs; j++){
m[j] = malloc(141 * sizeof(char));
to
for (j =0 ; j < numberOfMsgs; j++){
m[j] = malloc(141 * sizeof(char));
I'm still new to the forum so I apologize in advance for forum - etiquette issues.
I'm getting an error that makes no sense and I cannot find a reference to anywhere.
The code in question is in c, and was written for the purpose of reading a grid of numbers to find the largest product of four adjacent. It uses a two dimensional array to provide x-y like coordinates.
The error I'm getting is along the lines of ...
...../p11-largest-grid-product.c:30 function definition expected
This is confusing because I do not use any functions (besides the main function of course).
My code is as follows
#include <stdio.h>
int main
{
// decalare and value vars
int a, n, p, g = 0;
// initialize two dimensional array
int str[21][21];
// fill array 'str'
int str[1] = {08, 02, 22, 97, 38, 15, 00, 40, 00, 75, 04, 05, 07, 78, 52, 12, 50, 77, 91, 08};
int str[2] = {49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 04, 56, 62, 00};
int str[3] = {81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 03, 49, 13, 36, 65};
int str[4] = {52, 70, 95, 23, 04, 60, 11, 42, 69, 24, 68, 56, 01, 32, 56, 71, 37, 02, 36, 91};
int str[5] = {22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80};
int str[6] = {24, 47, 32, 60, 99, 03, 45, 02, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50};
int str[7] = {32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70};
int str[8] = {67, 26, 20, 68, 02, 62, 12, 20, 95, 63, 94, 39, 63, 08, 40, 91, 66, 49, 94, 21};
int str[9] = {24, 55, 58, 05, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72};
int str[10] = {21, 36, 23, 09, 75, 00, 76, 44, 20, 45, 35, 14, 00, 61, 33, 97, 34, 31, 33, 95};
int str[11] = {78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 03, 80, 04, 62, 16, 14, 09, 53, 56, 92};
int str[12] = {16, 39, 05, 42, 96, 35, 31, 47, 55, 58, 88, 24, 00, 17, 54, 24, 36, 29, 85, 57};
int str[13] = {86, 56, 00, 48, 35, 71, 89, 07, 05, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58};
int str[14] = {19, 80, 81, 68, 05, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 04, 89, 55, 40};
int str[15] = {04, 52, 08, 83, 97, 35, 99, 16, 07, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66};
int str[16] = {88, 36, 68, 87, 57, 62, 20, 72, 03, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69};
int str[17] = {04, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 08, 46, 29, 32, 40, 62, 76, 36};
int str[18] = {20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 04, 36, 16};
int str[19] = {20, 73, 35, 29, 78, 31, 90, 01, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 05, 54};
int str[20] = {01, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 01, 89, 19, 67, 48};
// horizontal
for( n = 1 ; n != 21 ; n++ )
{
for( a = 3 ; a != 20 ; a++ )
{
p = str[n][a] * str[n][a-1] * str[n][a-2] * str[n][a-3];
if( p > g )
{
g = p;
}
}
}
// vertical
for( a = 0 ; a != 20 ; a++ )
{
for( n = 4 ; n != 21 ; n++ )
{
p = str[n][a] * str[n-1][a] * str[n-2][a] * str[n-3][a];
if( p > g )
{
g = p;
}
}
}
// diagonal not /
for( n = 1 ; n != 18 ; n++ )
{
for( a = 0 ; a != 17 ; a++ )
{
p = str[n][a] * str[n+1][a+1] * str[n+2][a+2] * str[n+][a+3];
if( p > g )
{
g = p;
}
}
}
// diagonal /
for( n = 1 ; n != 18 ; n++ )
{
for( a = 3 ; a != 20 ; a++ )
{
p = str[n][a] * str[n+1][a-1] * str[n+2][a-2] * str[n+3][a-3];
if( p > g )
{
g = p;
}
}
}
getchar();
return 0;
}
Any explanation as to why these things worked/did not work and anything that can lead to a better understanding of these ideas will be appreciated. Links to helpful stuff are as well. I have tried to find a solution on my own (I'm self taught as I'm in high school) but with no luck.
Any tips for a good windows debugger for c are also appreciated.
The function definition expected error is probably caused by missing parentheses between main and the opening brace. Try this: int main () {.
Besides this, though, there are odd things happening in your code:
It initializes a 21 x 21 array of ints, but you call call it str as though you intend it to be an array of strings.
Arrays can only be initialized at declaration time. Once you've declared it, you cannot re-declare int str[1] and try to initialize values.
Arrays are zero-indexed; the first row of str[21][21] would be str[0], not str[1]. I'm not sure why you're leaving the top row out of your (attempted) initialization.
So even if you do rectify the function definition expected error by supplying the parentheses, the code is still broken in other ways.
I would hazard a guess that
p = str[n][a] * str[n+1][a+1] * str[n+2][a+2] * str[n+][a+3];
^^^
is the problem. You probably intended to add something to n.
EDIT
With the extra information in the comment, line 30 says
int main {
A function takes (possibly no) parameters, so try this
int main () {
While you are there watch out for a leading 0 meaning octal, making 08 and 09 make no sense.
You are not properly defining main, you have:
int main
{
...
But, you need:
int main()
{
...
in order for the compiler to know you are creating a function.
I've read questions about similar problems, but 2D or dynamic arrays' problems has been solved there. (There are pointers, but I'd like to do it without them.)
#include <stdio.h>
#include <stdlib.h>
int interseq ( int, int ); // interval sequence
int main()
{
int arr[100] = { 75, 47, 64, 45, 67, 51, 55, 36, 63, 30,
39, 58, 55, 67, 70, 44, 46, 51, 51, 61,
50, 54, 49, 51, 52, 54, 64, 68, 45, 40,
48, 60, 55, 37, 36, 13, 62, 53, 37, 53,
52, 49, 37, 54, 69, 44, 53, 58, 77, 46,
44, 63, 57, 64, 28, 46, 50, 57, 42, 72,
12, 69, 52, 53, 77, 50, 45, 49, 49, 46,
28, 40, 65, 25, 45, 45, 62, 28, 39, 69,
52, 57, 39, 73, 37, 46, 38, 65, 49, 58,
63, 30, 51, 48, 47, 56, 48, 41, 30, 54 };
printf("%d", interseq ( arr, diagArr) );
return 0;
}
/* User's function. Description: 'farr' is 'arr' and so on.. */
int interseq ( int farr, int fdiagArr)
{
int min, i;
for ( i = 0; i < 100; i++ ) // Finding the 'min' element.
if ( farr[i+1] < farr[i] ) // there are 2 errors
min = farr[i]; // there is 1 error
else
min = farr[i+1]; // there is 1 error
return 1;
}
The errors are the same:
error: subscripted value is neither array nor pointer nor vector
Make those into pointers:
int interseq(int *farr, int *fdiagArr)
^ ^
I can't see what diagArr is in your code so that part is speculation.
As simonc points in the comments, when i = 99, farr[i+1] will be illegal. You should stop earlier or change your algorithm.
Try this:
//int interseq ( int farr, int fdiagArr)
int interseq ( int farr[], int fdiagArr[])
I need fast way to generate ip numbers that are valid (reserved ips are valid too).
For now i am using this:
unsigned char *p_ip;
unsigned long ul_dst;
p_ip = (unsigned char*) &ul_dst;
for(int i=0;i<sizeof(unsigned long);i++)
*p_ip++ = rand()%255;
ip.sin_addr.s_addr = ul_dst;
But sometimes it generate non-valid numbers, but this code can generate about 10k of valid ips in a second. Can anyone contribute?
Thank you
calling rand() is probably the slowest part of your code, if you use the implementation of a random function found at http://en.wikipedia.org/wiki/Multiply-with-carry
This is an ultra fast C function for generating random numbers.
storing sizeof(unsigned long) in a registered variable i.e.:
register int size = sizeof(unsigned long)
should also help slightly.
Since you are using 4 chars = 4 x 8 byte memory, you can instead use a 32bit integer which will only require one memory address.
combining the bitshifting, new random method, registered variables, should reduce running times by quite a bit.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
uint32_t ul_dst;
init_rand(time(NULL));
uint32_t random_num = rand_cmwc();
ul_dst = (random_num >> 24 & 0xFF) << 24 |
(random_num >> 16 & 0xFF) << 16 |
(random_num >> 8 & 0xFF) << 8 |
(random_num & 0xFF);
printf("%u\n",ul_dst);
return 0;
Above this code I have the exact copy of the random function from wikipedia.
Hopefully this will run much faster.
We know the size of a 32bit int is 4*8 so no need for the sizeof anymore, and instead of %255 I replaced it with a 255 bit mask
Currently, your code writes four chars to memory. You can optimize this by writing one int32 to memory.
Roll your own random generator. For this purpose anything with a period of (1<<32) is valid, so you could construct a lineair congruential thing. (you would not need to construct from 4 separate characters, too)
Also, your *p_ip is uninitialised. you probably want a
p_ip = (unsigned char *) &ul_dst;
somewhere.
Building over #Serdalis idea of using init_rand(), maybe you can try something I had come across called Knuth Shuffle which will help you generate Random Numbers with a uniform Distribution.
The code will look like this I guess now but the below example uses rand():
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define TOTAL_VAL_COUNT 254
int byteval_array[TOTAL_VAL_COUNT] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
251, 252, 253, 254
};
unsigned char denominator = TOTAL_VAL_COUNT+1;
unsigned char generate_byte_val();
unsigned char generate_byte_val() {
unsigned char inx, random_val;
if (denominator == 1)
denominator = TOTAL_VAL_COUNT+1;
inx = rand() % denominator;
random_val = byteval_array[inx];
byteval_array[inx] = byteval_array[--denominator];
byteval_array[denominator] = random_val;
return random_val;
}
int main(int argc, char **argv) {
int i;
struct in_addr ip;
for (i = 1; i < 255; ++i) {
ip.s_addr = (generate_byte_val() |
(generate_byte_val() << 8) |
(generate_byte_val() << 16) |
(generate_byte_val() << 24));
printf ("IP = %s\n", inet_ntoa(ip));
}
}
HTH