This line arr = (char*)malloc (2 * sizeof (char)); will allocate memory for 2 bytes only. But you are overwriting the memory by accessing the more 8 or more than 8 byes. If you access more than two byes means, it will give some unpredictable issue. In case you want more memory please follow the below code.
#define USER_SIZE 10
arr = (char*)malloc ( USER_SIZE * sizeof (char));
Assign the value in USER_SIZE macro and then allocate the memory as much as you want.
Example for 2D pointer ( 5 X 10 )
#define ROW 5
#define COLUMN 10
main()
{
unsigned char **p = NULL, colum = 0;
p = malloc ( ROW * sizeof ( unsigned char *) );
for (;colum< ROW; ++colum )
{
p[colum] = malloc (COLUMN * sizeof (unsigned char ));
}
}
Answer from mahendiran.b on Stack OverflowThis line arr = (char*)malloc (2 * sizeof (char)); will allocate memory for 2 bytes only. But you are overwriting the memory by accessing the more 8 or more than 8 byes. If you access more than two byes means, it will give some unpredictable issue. In case you want more memory please follow the below code.
#define USER_SIZE 10
arr = (char*)malloc ( USER_SIZE * sizeof (char));
Assign the value in USER_SIZE macro and then allocate the memory as much as you want.
Example for 2D pointer ( 5 X 10 )
#define ROW 5
#define COLUMN 10
main()
{
unsigned char **p = NULL, colum = 0;
p = malloc ( ROW * sizeof ( unsigned char *) );
for (;colum< ROW; ++colum )
{
p[colum] = malloc (COLUMN * sizeof (unsigned char ));
}
}
What you are doing is called buffer overflow by writing beyond the bounds of memory allocated by malloc call. The compiler doesn't do bounds checking (it assumes you know what you are doing, and you only pay for what you use) and allow you to compile and run. However, it will lead to undefined behaviour and your program may crash. You shouldn't rely on such behaviour.
You, the programmer, has to make sure that you don't do illegal memory access. You should not cast the result of malloc. Also, malloc can fail to allocate memory in which case it returns NULL, the null pointer, which you should take care of. You can combine the two statements into one.
int length = 8; // you can also use a macro
char *arr = malloc(length * sizeof *arr);
if(arr) {
// malloc call successful
// do stuff with arr
}
How to print a char array in C through printf? - Stack Overflow
C Dynamic char array - Stack Overflow
How to declare a dynamic array of char in c - Stack Overflow
[question] How to print multiple chars from array?
This is C. You can't just call printf() and expect it to do the work for you. You need to iterate through the array with a for() or while() loop and print out each element.
Assuming it is an array of strings:
int i;
for (i=0; i<size; i++)
printf("array[%d] = %s\n", i, array[i]);
Please check this code. I believe that it does what you are expecting.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main(int argc, char** argv)
{
int size = 0;
int i;
char **array = malloc(0); //malloc for dynamic memory since the input size is unknown
static const char filename[] = "input.txt";
FILE *file = fopen(filename, "r");
if (file != NULL)
{
char line [ 128 ];
char delims[] = " ";
char *result = NULL;
while (fgets(line, sizeof line, file) != NULL)
{
result = strtok(line, delims); //separate by space
while( result != NULL )
{
size++;
array = realloc(array, size * sizeof (char*)); //declare array with unknown size
array[size - 1] = malloc(100 * sizeof(char)); // allocate memory for 100 chars
strcpy(array[size - 1], result); // copy the result
result = strtok( NULL, delims );
}
}
fclose(file);
}
else
{
perror(filename);
}
// return 0;
for (i = 0; i < size; i++)
{
printf("array[%d] = %s\n", i, array[i]);
}
// printf(array); //print array???
return (EXIT_SUCCESS);
}
The code posted is incorrect: a_static and b_static should be defined as arrays.
There are two ways to correct the code:
you can add null terminators to make these arrays proper C strings:
#include <stdio.h> int main(void) { char a_static[] = { 'q', 'w', 'e', 'r', '\0' }; char b_static[] = { 'a', 's', 'd', 'f', '\0' }; printf("value of a_static: %s\n", a_static); printf("value of b_static: %s\n", b_static); return 0; }Alternately,
printfcan print the contents of an array that is not null terminated using the precision field:#include <stdio.h> int main(void) { char a_static[] = { 'q', 'w', 'e', 'r' }; char b_static[] = { 'a', 's', 'd', 'f' }; printf("value of a_static: %.4s\n", a_static); printf("value of b_static: %.*s\n", (int)sizeof(b_static), b_static); return 0; }The precision given after the
.specifies the maximum number of characters to output from the string. It can be given as a decimal number or as*and provided as anintargument before thecharpointer.
This results in segmentation fault. ? because of the below statement
char a_static = {'q', 'w', 'e', 'r'};
a_static should be char array to hold multiple characters. make it like
char a_static[] = {'q', 'w', 'e', 'r','\0'}; /* add null terminator at end of array */
Similarly for b_static
char b_static[] = {'a', 's', 'd', 'f','\0'};
This:
realloc(input, (sizeof(char)));
is wrong. The realloc() function doesn't modify the given pointer (it can't!), it returns the new pointer. It can also fail, and return NULL.
Also, the second argument doesn't make any sense at all, it should be the new desired total size of the previously allocated buffer, but you're always passing (a very obscure) 1. It's not "grow this by this amount", it's the rather more low-level "attempt to grow this to this new size, and return the new location of the grown buffer".
Please read the documentation very carefully.
realloc(input, (sizeof(char)));
You are reallocating with same size (i.e 1 byte). It shoud be:
while((temp_c = getchar()) != '\n') {
realloc(input, (string_len + 1) * (sizeof(char)));
input[string_len++] = temp_c;
To get some memory to your string, you have to tell malloc how many bytes of memory you want. sizeof(char) returns 1, therefore, you'll only have 1 byte. In C, strings are terminated by the NULL byte (\0), and printf and others will print until they find that NULL terminator.
If you do something like this:
char *str = malloc(1);
*str = 'a';
printf("%s", str);
You will probably get a very strange output, since you have no NULL terminator.
When you use the unsigned x; str = malloc(x);, it's actually undefined how many bytes you have, since that x variable is not initialized.
Since your question is very unclear, what I can tell you (from what I think you're asking) is how to actually get space for a string of 63 characters plus the NULL terminating byte.
char *str = malloc(64);
strcpy(str, "Stack Overflow");
printf("%s", str);
That will do it.
Also note that the memory block returned by malloc will not be zeroed, therefore you can't possibly know what's in it (that could be the reason you're getting garbage when you're printing).
I recommend you read about memory allocation in a good C book or in Wikipedia...
After your edit and "MCVE"
I made some edits to what I think it is you want. The modifications are explained in the comments of the source. Let me know if you have any doubts.
#include <stdio.h> /* printf */
#include <stdlib.h> /* malloc, free, realloc */
#include <string.h> /* strcat */
#include <ctype.h> /* isalnum */
#include <conio.h> /* getch */
int main(void)
{
char add[2];
char str2[200];
char c;
int temp = -1;
int num = 0;
char *str3;
/* I just think 'count' is an int, since you didn't put it in the code,
* I also deduced that @count will be used as the length of @str3
*/
int count;
/* Here, count is not initialized, so you MUST initialize it in order
* to call malloc with it! Since it seems you want to add character by
* character using realloc, then we just malloc() 2 bytes - 1 for a
* character and one for the NULL terminator.
*/
count = 2;
str3 = malloc(count);
/* You will be using @strcat to append strings to @str3, so you need
* to put a NULL terminator in it, because strcat will look for that
* NULL byte to find where it should append
*/
*str3 = 0x0;
while((c = getch()) != '\r') {
for (int i = 0;i < 200; i++) {
if (str2[i] =='\0') {
num = i;
break;
}
}
if ((temp == -32) || (temp == 0)) {
/* empty */
} else {
if(isalnum((char)c) == 0)
{
if((c == '\'') || (c == -118) || (c == -115) || (c == -107) || (c == -123) || (c == -105)|| (c == 32))
{
/* this is not the optimal way of using realloc, because
* you should first check for errors, but will do for
* this example.
* You must assign the returned value of realloc to str3.
*
* Also, since @count contains the length
* of @str3, you need to increment it.
*/
str3 = realloc(str3, ++count);
printf("true: %c\n",c);
add[1] = '\0';
add[0] = c;
strcat(str3,add);
strcat(str2,add);
printf("str2: %s\n",str2);
printf("str3: %s\n",str3);
} else if (c == 8) {
printf("Deleting something...\n");
}
} else {
/* see notes above on realloc */
str3 = realloc(str3, ++count);
printf("true: %c\n",c);
add[1] = '\0';
add[0] = c;
strcat(str3,add);
strcat(str2,add);
printf("str2: %s\n",str2);
printf("str3: %s\n",str3);
}
}
printf("ASCII Code: %d\n",c);
temp = c;
}
return 0;
}
In the first two cases, you are only allocating enough space for a single char. If you attempt to write more than one to that block of memory, you'll write past the end of the memory that was allocated for you. Doing so invokes undefined behavior, which in this case manifests as printing strange characters.
In the third case, you allocate x bytes of memory, however x is uninitialized and has an indeterminate value. Reading an indeterminate value is also undefined behavior. In this case it happens to work because the indeterminate value happens to be a valid value and is large enough to hold the string you want, however you can't depend on that behavior.
You need to allocate a byte for every character that you'll need, plus 1 for the terminating null byte that ends a string in C.
i want to be able to print out multiple values from an array without having to re-write the char name and array number multiple times, is this possible? example...
char letters[] = {'a','b','c','d'};
printf("%c%c%c%c", letters[0], letters[1], letters[2]);i want to make that code cleaner and easier to use/understand. I thought i'd be able to use
printf("%c", letters[0][1][2]);or seperated by commas, but that doesn't work either. Any suggestions?
hey! I am stuck on this question, I have to cin and cout a dynamic array of characters (not using library function/ c++ string types), here are the two issues i am facing:
-
I do not know how long the name would be so should I just take a precondition that it should be smaller than let's say 100? or is there a way that I can create a dynamic array without specifying coloum size?
-
this code that i came up with is producing weird result and i have no clue how to correct it T_T
I would be really thankful if you all can help me with this T_T.
my needed output should look something like:
enter name #1: abc def
enter name #2: ghi jkl...
.
.
.
enter name #n: nnn mmm
int main()
{
int n, j=0;
cout<<"How many names do you want to enter ? ";
cin>>n;
char** name = new char*[n];
for(int i=0; i<n; i++)
{
name[i]=new char[100];
}
for(int i=0; i<n; i++)
{
cout<<"enter name #"<<i+1 <<" :";
do
{
cin>>name[i][j];
j++;
}while(name[i][j]!='\n');
}
for(int i=0; i<n; i++)
{
for(int j=0; name[i][j]!='\n' ; j++)
{
cout<<name[i][j];
}
cout<<endl;
}
}Edit: Thank You so much for helping me with this problem however I figured a way to do it, it's definitely not the best or the most useful but our professor won't vibe with any other straight ways lmao here's what I came up with and the output I get, please let me know what yall think!
int main()
{
int n;
cout<<"How many names do you want to enter ? ";
cin>>n;
char** lastname = new char*[n];
for(int i=0; i<n; i++)
lastname[i]=new char[100];
char ** firstname = new char*[n];
for(int i=0; i<n; i++)
firstname[i]=new char[100];
for(int i=0; i<n; i++)
{
cout<<"enter name #"<<i+1 <<" :";
cin>>firstname[i]>>lastname[i];
}
for(int i=0; i<n; i++)
{
cout<<firstname[i]<<" "<<lastname[i];
cout<<endl;
}
}
/* OUTPUT :
How many names do you want to enter ? 3
enter name #1 :Fucker Certified
enter name #2 :Flex Offender
enter name #3 :Billy Balls
Fucker Certified
Flex Offender
Billy Balls
*/I am pretty sure it's not the most efficient but this was all I could think of T_T
once again Thank You so muchhh!!
This is problematic:
char Array[SIZE], *Array_ptr = strtok(Array, " .");
You are declaring the array, then trying to use strtok on the uninitialized array. You probably meant to do this:
char Array[SIZE], *Array_ptr = 0;
StrInput(Array, SIZE);
Array_ptr = strtok(Array, " .");
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 10
#define MIN_SIZE 2
void StrInput(char str[], int maxChars);
int main(int argc, char *argv[]){
char Array[SIZE], *Array_ptr, *strwk;
StrInput(Array, SIZE);
int i=0;
strwk=strdup(Array);//strtok would change the string. so make a copy.
Array_ptr=strtok(strwk, " .");
while (Array_ptr != NULL){
++i;//countup element
Array_ptr = strtok(NULL, " .");
}
int *Malloc_Array_ptr = (int*)malloc(i* sizeof(int));
i=0;
strcpy(strwk, Array);
Array_ptr = strtok(strwk, " .");
while (Array_ptr != NULL){
Malloc_Array_ptr[i] = atoi(Array_ptr);
++i;
Array_ptr = strtok(NULL, " .");
}
free(strwk);
int j;
//check print
for(j=0;j<i;++j)
printf("%d ", Malloc_Array_ptr[j]);
printf("\n");
// printf("Show me the money: %s \n", Malloc_Array_ptr);//Malloc_Array_ptr isn't (char*).
system("PAUSE");
return 0;
}
/*----------------------------------------------------------------------*/
void StrInput(char str[], int maxChars){
int i=0, ch;//str_lenght: unused
int InputOver = 0;
printf("input numbers :");
for(i=0;(ch = getchar()) != '\n';++i){
if(i > maxChars -1){//-1: for EOS(\0)
i = maxChars - 1;
InputOver = !InputOver;//true
break;
}
str[i]=(char)ch;
}
str[i]='\0';
if (InputOver || i<MIN_SIZE){
printf("Your sumbition dosn't fit the size criteria.\n");
printf("Please reenter:\n\n");
while('\n'!= ch){//clear input
ch = getchar();
}
StrInput(str, maxChars);
}
}
There are a number of things I would change here, so I'm going to go through the process incrementally, applying changes to the whole file in passes rather than in chunks. I think this should make it more clear why the changes are implemented.
C99 Note
You should have access to, at the very least, a C99 compiler. If that's not true, you can ignore this first point, but if it is, you should change your counter declarations to be inside the first for clause.
for (int i=0;i<n;i++)
Pointers
In initArr, you both return the int array and assign it to the provided out parameter, arr. Why? Out parameters make code confusing and hard to follow! They make sense if you're performing the array allocation somewhere else, but since you're performing the array allocation inside initArr, just drop the arr parameter and return the value.
As a side effect of this, since you no longer need a double pointer, you can replace your dereferences with simple array accesses.
int * initArr (int n)
{
int * arr = (int *) malloc(sizeof(int*)*n);
printf("size is %d\n", sizeof(arr));
for (int i=0;i<n;i++)
{
arr[i]=i+10;
}
return arr;
}
Next, why are you passing a double pointer (int**) to printArr? More importantly, why does printArr have a return value if it's a purely side-effectful function? Change the parameter to int* and make the function return void.
void printArr (int * arr, int n)
{
for (int i=0;i<n;i++)
{
printf("Arr element %d is %d\n", i, arr[i]);
}
}
This also simplifies the main function.
int main(void) {
int * arr2 = initArr(10);
printArr(arr2,10);
return 0;
}
Next, let's take a look at the allocation itself (the one in initArr). First of all, you cast to (int *) manually, which is unnecessary and downright discouraged in C. If you're using C++, it's necessary (though you shouldn't need malloc in C++, anyway), but with a C compiler, just drop it.
Second of all, you are not actually allocating the right data! You're allocating n slots for int* values—int pointers. You actually want int data. This might not matter depending on your architecture and compiler, but it's still poor code. Fortunately, you can actually fool-proof this—don't pass an explicit type of sizeof at all! Just deference arr itself, and the compiler will calculate that value's size.
Those changes simplify the allocation to this:
int * arr = malloc(sizeof(*arr)*n);
Finally, the line just after that—the printf line—is useless. It will always print the same value because it's checking the size of a pointer, which is always the same size regardless of type (though it can change on different architectures). That said, the line doesn't make any sense there. A function called initArr shouldn't have side effects, anyway. Just take it out.
Style and Warnings
I'm not sure if you just omitted it from your code, but your code depends on functions declared in external header files in the standard library. Include these at the top of your file.
#include <stdlib.h>
#include <stdio.h>
Next, let's talk about code style. You are writing some very densely-packed expressions in some places. Some whitespace can make code much more readable! For example, change the for loops to this:
for (int i = 0; i < n; i++)
Similarly, change your allocation to this:
int * arr = malloc(sizeof(*arr) * n);
Proper spacing makes code more readable and therefore more maintainable!
Finally, let's talk about pointer declarations. You are declaring your pointers with the asterisks just sort of "floating". This is actually not a bad compromise. Some people prefer them to be grouped with the type (int* foo), others with the name (int *foo). I prefer the former style, so in my final copy of the code, I changed them accordingly, but this is often merely personal preference.
Result
Here is all the code as it stands with the above changes implemented! Not only is it more readable due to style, but it's easier to understand the control flow since it no longer unnecessarily indirects variables via reference.
#include <stdlib.h>
#include <stdio.h>
int* initArr(int n)
{
int* arr = malloc(sizeof(*arr) * n);
for (int i = 0; i < n; i++) {
arr[i] = i + 10;
}
return arr;
}
void printArr(int* arr, int n)
{
for (int i = 0; i < n; i++)
{
printf("Arr element %d is %d\n", i, arr[i]);
}
}
int main(void) {
int* arr2 = initArr(10);
printArr(arr2, 10);
return 0;
}
Extra Notes
Can I use
arr[i]anywhere in the functions instead of**arr? (Gave error when I tried it)
You can! But * has lower precedence than array subscript ([]), so you'd need to use grouping operators
(*arr)[i]
This became unnecessary with the other changes, though.
What is the most common way of dealing with arrays when writing professional code? Is my approach correct?
Depends on the situation. Honestly, the best away to handle arrays is to not use them—if you're using a language with any more power than C, you should have higher-level language constructs (std::vector, ArrayList, etc.). However, if you have to use C, abstracting them behind an API is a good start.
One issue I'm encountering is having no way to tell printArr() what the size of the array is.
Yes, in C, arrays are just blocks of memory, so you can't get their length at runtime because it's not stored anywhere! If you wanted to do this, though, you could encapsulate your array in a struct.
typedef struct my_array {
unsigned int length;
int* data;
} my_array_t;
You could then return a my_array_t from initArr and pass a my_array_t to printArr, which could use arr.length to get the length.
Return values
initArrcommunicates the start address via both the return value and a pass-by-reference parameter. It surely is redundant. Normally you'd pick one of two possible signatures:int * initArr(int size); void initArr(int ** arr, int size);
and stick to it.
printArr, as the name suggests, only produces a side effect of values being printed. It has nothing to report back except possibly errors encountered while printing. Make itvoid printArr(int *, int).
(Ab)use of
sizeofinitArrallocates an array ofnunits of a pointer size. This works by coincidence: in pretty much any platform space taken by a pointer is enough to accomodate an integer. However it is not guaranteed.printf("size is %d\n", sizeof(*arr))is totally misleading. It is equivalent toprintf("size is %d\n", sizeof(int *)), and doesn't depend on how many bytes are actually allocated. Try to pass size 0 toinitArr.
You got to understand behavior behind your program. So when you load your program it is given N bytes in memory and that N bytes gets reused many times and not erased. So in first instance your program have loaded some data into spot where s[0] would later reside, where as in second something was loaded where s[2] as well. That is why you are getting different output in these 2 cases.
So to sum it up: Your array is not initiated to 0 or unless you do it your self, it is given memory that have been previously used by the same program. To do it as it was pointed before you have to do this:
char s[10] = " ";
....
One more thing I see is you were not expecting space before a, in C/C++/Java array indexes start at 0. So if you do:
char s[4];
s[1] = 'a';
s[2] = 'b';
s[3] = '\0';
print ("%s", s);
you would probably get:
@ab
@ comes up because there was nothing written by you as programmer in memory spot where s[0] resides.
Note that every time you have string in C you have to terminate it with '\0' character.
The problem is that you didn't initialise your array. In order to get that output you can do it in this way:
char s[10];
for(int i=0;i<10;i++)
{
s[i] = ' ';
}
s[1]='a';
s[6]='4';
for(int i=0;i<10;i++)
printf("%c",s[i]);