Integer increment (++) crashes application - c

I am trying to write a small program in C but I am stuck trying to increment an int.
#include<stdio.h>
#include<string.h>
char * compress(char *input, int size){
char *inputCopy;
char compressedString[100];
snprintf(inputCopy, size, "%s", input);
int i = 0;
int counter;
int j;
while(i < size){
counter = 1;
j = i;
while (inputCopy[j] == inputCopy[j + 1] && j < size){
j++;
printf("same! \n");
counter++; // When this line is commented out it works.
}
if (i != j){
i = j;
}else{
i++;
}
}
return inputCopy;
}
main(){
char test[10] = "aaaaaaasdd";
printf("%s \n", compress(test, 10));
printf("%s", test);
return 0;
}
The counter++ line for some reason is making my program crash.
I know it is probably something simple, but can someone point out to me why this is not working?

You need to check j < size first, and strengthen it to j + 1 < size else you run the risk of an out-of-bounds array access, which is undefined behaviour:
while (j + 1 < size && inputCopy[j] == inputCopy[j + 1]){
(The right hand argument of && is only evaluated if j + 1 < size is 1.)
And where is the memory allocated for inputCopy?

You're not allocating data for snprintf. inputCopy is uninitialized, so it's probably writing over the memory used by counter. Make sure you allocate the necessary memory.
Unrelated to this crash, but you have a potential for invalid reads (inputCopy[j + 1]). Switch j < size to (j + 1) < size and move it to the beginning of the while so you'll short circuit.
valgrind (or Clang's address sanitizer) can help catch both of these issues if you're on a Linux system.

Here you define test as an array of length 10:
char test[10] = "aaaaaaasdd";
Then you pass it to compress with 10 as the size:
printf("%s \n", compress(test, 10));
This conditional will remain true while i is 0 through 9:
while(i < size){
And same for j:
j = i;
And when j is equal to 9, this line will try to access element j + 1, which is 10, of your array, which is out of bounds:
while (inputCopy[j] == inputCopy[j + 1] && j < size){
This will cause undefined behavior. Most likely this is the source of your crash, and the thing with counter is incidental.
EDIT: Aaaaaand you're also not allocating any memory for inputCopy on this line, which will also lead to undefined behavior:
snprintf(inputCopy, size, "%s", input);

It is illegal to write to inputCopy. It points to random memory:
char *inputCopy;
char compressedString[100];
snprintf(inputCopy, size, "%s", input); // !? memory not allocated for the inputCopy

Related

I have troubles printing arrays of characters in C

the problem is that the following code prints nothing. And I tried very hard, using different methods, I used fixed sized arrays, I tried to print the array from a void function, I tried printf and sprintf, I tried with static s variable, I tried to loop the array and print charcacter the result is always the same, 0 errors, 0 warnings and never print the result. After about 30 seconds, the program automatically terminate with the following output:
Convert 56 to ascii:
Process returned -1073741819 (0xC0000005) execution time : 4.763 s
Press any key to continue.
Here's the code (I maybe used too many includes, but this is because I tried everything):
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void reverse(char s[])
{
int c, i, j;
for(i = 0, j = strlen(s)-1; i < j; i++,j++){
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
char * itoascii(int n)
{ char *s = malloc(10);
/*if(s == NULL)
return NULL;*/
int i, sign;
if((sign = n) < 0)
n = -n; // if n is negative, make it positive. And store the sign into sign
i = 0;
do {
s[i++] = n % 10 + '0'; // turn a digit into a string and then increment i
}while(( n /= 10) > 0);
if(sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
return s;
}
int main()
{ int n;
n = 56;
printf("Convert %d to ascii:\n", n);
char *buf = itoascii(n);
sprintf(buf, "%s\n");
return 0;
}
Yes, the problem was the y++ stuff. The fact is that I copied this code from a K&R edition with errata. In the book I found y++ and I blindy trusted the function, I never consider it in my debugging assuming the problem was due to improper pointer usage or other things.
Sure the code may be improved. printf es better than sprintf and I also must free the allocated memory with malloc. I also have to remove the extra unused include.
Thanks for your comments!
Code has at least these problems:
10 insufficient for large int. Suggest at least 12. Maybe sizeof(int)*CHAR_BIT/3 + 3 for an approximate generalization.
n = -n; is UB when n == INT_MIN.
Wrong increment
//for(i = 0, j = strlen(s)-1; i < j; i++,j++){
for(i = 0, j = strlen(s)-1; i < j; i++,j--){

Array size redefinition

So basically according to definition of array we cannot change array size. But if I am adding element to a same array by shifting other elements to the right of array, so the array size is going to increase.
How this is possible?
#include<stdio.h>
int main() {
int n, j, k, item;
printf("Enter size of array:\n");
scanf("%d", &n);
printf("Enter element to insert and position of element:\n");
scanf("%d,%d", &item, &k);
int a[n];
for (j = 0; j < n; j++) {
printf("Enter a[%d] element:\n", j);
scanf("%d", &a[j]);
}
j = n - 1;
while (j >= k - 1) {
a[j + 1] = a[j];
j = j - 1;
}
a[k - 1] = item;
for (j = 0; j <= n; j++) {
printf("%d\n", a[j]);
}
}
Shifting the contents of the array to the right will not resize the array. If the array was not already large enough to hold the result of the shift, then you have overrun the array object, and have induced undefined behavior.
There is no way to dynamically increase the size of a variable with static or auto duration (e.g., global or local variables), and this includes arrays. If your compiler supports variable length arrays (VLAs), changing the value of the expression controlling the dimension of the array does not affect the array's size.
int main (void) {
int n = 3;
int v[n];
printf("%zu\n", sizeof(v));
++n;
printf("%zu\n", sizeof(v));
}
The program above will print the same value twice.
I am not entirely sure what you're asking, but for any readers interested in knowing how to dynamically change the size of an array in C: if an array is declared in stack memory, its size cannot change. However, a block of memory intended to be used as an array is declared on the heap (i.e. with malloc or calloc), can be reallocated with a different size if necessary:
int *data = malloc(10 * sizeof(int)), *data2 = NULL;
int i;
if(data == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i < 10; i++)
{
data[i] = i;
}
data2 = realloc(data, 11 * sizeof(int));
if(data2 == NULL)
{
free(data);
perror("realloc");
exit(EXIT_FAILURE);
}
else
{
data = data2;
}
data[10] = 10;
for (i = 0; i < 11; i++)
printf("%d ", data[i]);
free(data);
data = NULL;
Shifting elements in an array down one element will not change its size.
If you declare an array as
T a[N]; // assume N is a constant expression
then a can only ever hold N elements of type T - no more, no less. You cannot add extra elements to the array, nor can you remove elements from the array.
However...
C does not force any bounds checking on array subscripting, so it's possible that you can read or write past the end of the array such as
a[N + 2] = x;
The behavior on doing so is undefined - your program may work as expected, or it may crash immediately, or you may corrupt other objects in the program. The runtime environment will (most likely) not throw an IndexOutOfBounds-type exception.
There is a thing called a variable-length array that was added in C99, where the array size is not a constant expression:
size_t size = some_value();
T a[size];
Variable length arrays are only variable length in the sense that their size isn't determined until runtime - however, once defined, their size is fixed throughout their lifetime, and like regular arrays, they cannot grow as new items are added.
If you dynamically allocate a chunk of memory using
T *a = malloc( sizeof *a * some_size );
then you can grow or shrink that chunk of memory using realloc:
T *tmp = realloc( a, sizeof *a * (some_size * 2) );
if ( tmp )
{
a = tmp;
some_size *= 2;
}
.... array we cannot change .. But if I (do something special) ... the array size is going to increase.
How this is possible?
Undefined behavior
Arrays cannot change size once defined.
Code attempts to assign a[j + 1] with j = n-1 and that is a[n]. This is outside array a[] and so undefined behavior. Rest of code is irrelevant for at that point anything is possible, code crash, error report, even apparent successful array expansion, etc.
int a[n];
...
j = n - 1;
while (j >= k - 1) {
a[j + 1] = a[j]; // To attempt access to `a[n]` is UB

Expanding the size of an array of strings in c

I am trying to get strings from the user and then expand the size of the strings if they enter a long string and also expand the size of the array holding the strings if they enter more strings than expected.Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
int main(int argc, char* argv[])
{
int number_of_strings = 5;
int string_size = 5;
int count = 0;
char **array = (char**)calloc(number_of_strings, sizeof(char*));
for (int i = 0; i < number_of_strings; i++)
{
array[i] = (char*)calloc(string_size + 1, sizeof(char));
}
////////////////////////////MAIN PART///////////////////////////////////////////////
int arr_size = number_of_strings;
int str_count = 0; //Total number of input strings counter
for (int j = 0; j < arr_size; j++)
{
if (arr_size >= str_count) //Check if the number of input strings is more than expected
{
array = (char**)realloc(array, (arr_size + 1) * sizeof(char*)); //allocate memory for 1 more string
arr_size++; //Increase the loop rounds
}
int str_size = string_size;
int char_count = 0; //Total number of input characters counter
for (int h = 0; h < str_size; h++)
{
if (str_size >= char_count) //Check if the input string size is more than expected
{
array[j] = (char*)realloc(array[j], (str_size + 1) * sizeof(char)); //allocate memory for 1 more char
str_size++; //Increase the loop rounds
}
scanf(" %c", &array[j][h]); //get a single char
char_count++; //Increment the total input character count
}
str_count++; //Increment the total input string count
}
////////////////////////////////////////////////////////////////////////////////////
for (int k = 0; k < number_of_strings; k++)
{
printf("%s", array[k]);
free(array[k]);
}
free(array);
return 0;
}
Input:Thisisnot whatitlooks likebut Idon't knowwhy isthis happening
Output: Empty Stdout . Time limit exceeded
Expected Output: ThisisnotwhatitlookslikebutIdon'tknowwhyisthishappening
The program waits for user input for a long time and it doesn't stop scanning for inputs, even if the user doesn't enter any input and so eventually the program crashes.
I think the error is caused due to improper reallocation of the array. Any idea about why is this error caused and how can it be fixed is greatly appreciated. Thanks!
It is unclear what you are trying to do. Here are some problems in the code:
you purposely ignore whitespace from the input, so how can you detect string boundaries?
all of the input is clumped into a single string the inner loop never stops.
you do not check for EOF either: if the end of the input stream is encountered, the loop continues, reallocating memory until a system crash or an allocation failure...
allocation failure is not tested either, so undefined behavior in all cases.
there is no need to cast the return value of malloc and calloc in C. It is necessary in C++, but you would definitely want to use a different approach in C++. To avoid type discrepancies, you can use the type of the destination pointer instead of hard coding it: to reallocate the array, replace array = (char**)realloc(array, (arr_size + 1) * sizeof(char*)); with
array = realloc(array, sizeof(*array) * (arr_size + 1));

Using printf( ) in a for loop

When attempting this (code below), the console doesn't even request an input value, then spits out a random number (likely from a number previously stored at the location).
Why does this not work and how can i fix it?
int main( ) {
int arr[3];
for(int i = sizeof(arr); i <= 0; i--) {
scanf("%d", &arr[i]);
}
printf("%d", arr[2]);
return 0;
}
There are two things that are wrong.
Assuming you want the number of elements in the array, it is done, using:
size_t len = sizeof(arr) / sizeof(*arr)
sizeof gives the actual size (number of bytes allocated for arr.
You should start with len - 1 and not len.
NOTE: Array indexing is 0 based not 1 based, so the array elements are indexed from 0 to 2 But you would have tried to access arr[3], which can result in undefined behaviour.
You wrote i <= 0. So, i starts from let's say 2, is 2 <= 0 ? NO!
Hence it will never go inside the loop. The correct condition is i >= 0
int len = sizeof(arr) / sizeof(*arr);
for(int i = len - 1; i >= 0; i--)
Well, I don't know why you are taking reverse order input, but a general convention is to take input using:
size_t len = sizeof(arr)/sizeof(*arr);
for (i = 0; i < len; i++)
{
// take input
}
EDIT:
From other comments it seems that you don't understand the for loop.
Have a look in this answer
Please comment for any further clarification.
i <= 0
the code can never enter the loop since the initial value of i is greater than zero.
It is important to note that in C, other than languages like Java/Python, you must explicitly know the length of the array, sizeof will NOT give you the amount of items in the array.
int main() {
int arr[3];
int itemsInArray = 3;
for(int i = itemsInArray-1; i >= 0; i--) {
scanf("%d", &arr[i]);
}
printf("%d", arr[2]);
return 0;
};
Since i-- will decrease the value of i , and the condition for loop is i <=0 to start the loop the i must be 0 or negative.Since arr[3] will return 12(3 elements and each has 4 bytes(int has 4 bytes)), the value will be posivite,greater than 0 so we need to change the loop condition to check if i is positive
#include <stdio.h>
int main( ) {
int arr[3]={0};
int i = sizeof(arr)/sizeof(arr[0]) -1;
for(; i >= 0; i--) {
scanf("%d", &arr[i]);
}
printf("%d", arr[2]);
return 0;
}
There are a couple of issues with your code: first of all, sizeof(arr) won't return "3" as you probably thought; "arr" is a pointer to arr[0], so you are requesting the size of an int pointer.
Secondly, i <= 0 prevent the loop to even be executed.
Finally, please set array to zero while declarating, as best practice, ie:
int arr[3] = {0};
EDIT: i wrong-spelled my thoughts: you are requesting the size of the whole memory area allocated for the array.
Comments below are corrected though.

C programming Pointer and String operations

So I have an assignment where I need to change certain functions by substituting pointer operations for array operations, and by substituting string operations for character operations. Now I have a basic understanding of pointers, arrays, strings, etc. but I cant understand what it is I have to do, and how I should go about doing it. Here is the code:
#include <stdio.h>
#pragma warning(disable: 4996)
// This program exercises the operations of pointers and arrays
#define maxrow 50
#define maxcolumn 50
char maze[maxrow][maxcolumn]; // Define a static array of arrays of characters.
int lastrow = 0;
// Forward Declarations
#define triple(x) x % 3 == 0
void initialization(int, int);
void randommaze(int, int);
void printmaze(int, int);
void initialization(int r, int c) {
int i, j;
for (i = 0; i < r; i++){
maze[i][0] = 'X'; // add border
maze[i][c - 1] = 'X'; // add border
maze[i][c] = '\0'; // add string terminator
for (j = 1; j < c - 1; j++)
{
if ((i == 0) || (i == r - 1))
maze[i][j] = 'X'; // add border
else
maze[i][j] = ' '; // initialize with space
}
}
}
// Add 'X' into the maze at random positions
void randommaze(int r, int c) {
int i, j, d;
for (i = 1; i < r - 1; i++) {
for (j = 1; j < c - 2; j++) {
d = rand();
if (triple(d))
{
maze[i][j] = 'X';
}
}
}
i = rand() % (r - 2) + 1;
j = rand() % (c - 3) + 1;
maze[i][j] = 'S'; // define Starting point
do
{
i = rand() % (r - 2) + 1;
j = rand() % (c - 3) + 1;
} while (maze[i][j] == 'S');
maze[i][j] = 'G'; // define Goal point
}
// Print the maze
void printmaze(int r, int c) {
int i, j;
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++)
printf("%c", maze[i][j]);
printf("\n");
}
}
void main() {
int row, column;
printf("Please enter two integers, which must be greater than 3 and less than maxrow and maxcolomn, respectively\n");
scanf("%d\n%d", &row, &column);
while ((row <= 3) || (column <= 3) || (row >= maxrow) || (column >= maxcolumn)) {
printf("both integers must be greater than 3. Row must be less than %d, and column less than %d. Please reenter\n", maxrow, maxcolumn);
scanf("%d\n%d", &row, &column);
}
initialization(row, column);
randommaze(row, column);
printmaze(row, column);
//encryptmaze(row, column);
//printmaze(row, column);
//decryptmaze(row, column);
//printmaze(row, column);
}
Here are the questions I am struggling on:
Rewrite the function randommaze(row, column) by substituting pointer operations for all array operations. You may not use indexed operation like maze[i][j], except getting the initial value of the pointer.
Rewrite the function printmaze(row, column) by substituting string operations for all character operations.
If someone could please explain to me what I should be doing and how I should be doing it I would really appreciate it. Thanks!
Question 2.:
An array can be used as a pointer to it's first member. So, for example, array[0] and *array return the same thing - the value of the first element of the array. Since arrays are contiguous blocks of memory, if you increment (or add an offset to) a pointer that's pointing to the beginning of an array, you point to the next element of the array. That means that array[1] and *(array + 1) are the same thing.
If you a have a for loop that iterates indexing an array, you could just as well write it using pointer increments. Example:
/* Loop indexing an array */
int my_array [10];
int i = 0;
for(; i < 10; ++i) {
my_array[i] = 0;
}
/* Loop by offsetting a pointer */
int my_array [10];
int i = 0;
int *ptr = my_array; /* Make it point to the first member of the array*/
for(; i < 10; ++i) [
*(ptr + i) = 0;
}
/* Looping by incrementing the pointer */
int my_array [10];
int *ptr = my_array; /* Make it point to the first member of the array */
int *end_ptr = my_array + 10; /* Make a pointer pointing to one past the end of the array */
for(; ptr != end; ++ptr) [
*ptr = 0;
}
All these code examples do the same thing. Assign 0 to all members of the array. If you a have a multidimensional array, just remember that it's still just a contiguous block of memory.
Question 3.:
This question is not so clear to me, so my interpretation of what you're expected to do may be a bit off, but since you're just using printf to print single chars, I'm guessing that you should use a function to output a single char instead. Something like putchar.
Hopefully, this will steer you in the right direction.
It sounds as though you are engaged in a data structures course. The first challenge is to build an array mapping function. For example:
int main(int argc, char **argv)
{
int values[20][40];
values[0][0] = 1;
values[10][10] = 20;
/* Let's print these two ways */
printf("0,0: %d 10,10: %d\n", values[0][0], values[10][10]);
printf("0,0: %d 10,10: %d\n", *((*values) + (sizeof(int) * 0) + sizeof(int) * 0)), *((*values) + (sizeof(int) * 10) + sizeof(int) * 10)));
}
What we are doing is obtaining the address of the very first byte of memory in the 2d array (*values) and then adding a raw number of bytes as an offset to it to locate the value from the "array" that we'd like to access.
One of the main points of an exercise like this is to show you how the language actually works under the hood. This his how array mapping functions work generally and can be used as the basis, for example, for a language or compiler design course later, in addition to fast implementations of far more complex memory structures.
As to the second piece, I'm not super clear on this since there are no actual "string" operations built into C. I'd need a bit more detail there.

Resources