C - What's wrong with my code (malloc, char*) - c

I just want you to ask what did I do wrong with this code.
I wrote a function that take a char* in parameter, I want to modify it directly without returning smthg, and reverse the string.
#include <iostream>
void reverseString(char *p_string){
int length = strlen(p_string);
int r_it = length - 1;
char* tmp = (char*)malloc(length);
int last_it = 0;
for (int i = 0; i != length; i++){
tmp[i] = p_string[r_it];
r_it--;
last_it++;
}
tmp[last_it] = '\0';
strcpy_s(p_string, length + 1, tmp);
//free(tmp);
}
int main(){
char str[] = "StackOverflow";
reverseString(str);
std::cout << str << std::endl;
system("pause");
}
I'm used to C++ and don't often use C functions like malloc/free/strcpy...
Here, my problem is, when I alloc memory for my temporary char, I called mallec(length) for length = 13 in this case, char = 1 bytes so it should be allocate memory for 13 char is that right?
Problem is allocate more space than need so i need to use '\0' before my strcpy_s if not it breaks.
Did I do a mistake somewhere?
Also, when i call free(tmp), it breaks too and say heap corruption, but I didn't free the memory before that.
Thanks for helping !

I took your original code and added a simple '+1' to the size of the malloc and got a passing result.
Not sure if your exercise is related specifically to the use of malloc, but have you considered doing the reversal directly inside the original string?
For example:
void reverseString(char *p_string){
char* p_end = p_string+strlen(p_string)-1;
char t;
while (p_end > p_string)
{
t = *p_end;
*p_end-- = *p_string;
*p_string++ = t;
}
}
int main(){
char str[] = "StackOverflow";
reverseString(str);
std::cout << str << std::endl;
system("pause");
}
If you are required to use malloc, then you need to ensure that you allocate enough space for string which includes the '\0'

You must use
int length = strlen(p_string);
int r_it = length - 1;
char* tmp = (char*)malloc(length+1);
Since strlen doesn't count the \0 character. So this will fail if you don't use length+1:
tmp[last_it] = '\0';
The length of a C string is determined by the terminating
null-character: A C string is as long as the number of characters
between the beginning of the string and the terminating null character
(without including the terminating null character itself).
http://www.cplusplus.com/reference/cstring/strlen/
Btw. C99 support semi dynamic arrays. So could you try this:
char tmp[length+1];
Source:
http://en.wikipedia.org/wiki/Variable-length_array
float read_and_process(int n)
{
float vals[n];
for (int i = 0; i < n; i++)
vals[i] = read_val();
return process(vals, n);
}

Check the below C code:
The memory allocated to tmp should be length+1 as done below and also there are many unnecessary variables which can be avoided.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void reverseString(char *p_string){
int i;
int length = strlen(p_string);
int r_it = length - 1;
char* tmp = (char*)malloc(length+1);
for (i = 0; i != length; i++){
tmp[i] = p_string[r_it--];
}
tmp[i] = '\0';
strcpy(p_string, tmp);
return;
}
int main(){
char str[] = "StackOverflow";
reverseString(str);
printf("%s",str);
return 0;
}

There is nothing fundamentally wrong with your approach, just some of the details. Since I am not sure how you found out that the sizeof(tmp) is 32, I modified your code to the one below which includes a few printfs and some minor changes:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void reverseString(char *p_string)
{
size_t length = strlen(p_string);
size_t r_it = length - 1;
char* tmp = (char*)malloc(length+1);
int last_it = 0;
size_t i=0;
printf("strlen(p_string) = %d\n", strlen(p_string));
printf("Before: strlen(tmp) = %d\n", strlen(tmp));
for (i = 0; i != length; i++) {
tmp[i] = p_string[r_it];
r_it--;
last_it++;
}
tmp[last_it] = '\0';
printf("After: strlen(tmp) = %d\n", strlen(tmp));
strcpy(p_string, tmp);
free(tmp);
}
int main()
{
char str[] = "StackOverflow";
reverseString(str);
printf("%s\n", str);
return 0;
}
First, I have removed all C++ specific code - you can now compile this with gcc. Running this code yields this output:
sizeof(p_string) = 13
Before: strlen(tmp) = 0
After: strlen(tmp) = 13
wolfrevOkcatS
This is to be expected - strlen basically counts bytes until it hits the \0 character and so the first time we print the size using strlen, it returns 0 since we just allocated the memory. As another poster suggested, we have to allocate 1 extra byte to store the \0 in our new string.
Once the reverse is complete, 13 bytes would have been copied over to this memory and the second strlen returns the expected answer.

Related

Add a char padding in C strings

I am trying to implement this simple encryption method for a a list of numbers, the encryption is like this:
we add the 1st element of the list before every element of the entire list of numbers,
if we have:
char array = "356307042441013"
the first number is 3, that means we need to add it before every element of the list of numbers:
'33 35 36 33 30 37 30 34 32 34 34 31 30 31 33'
char result= "333536333037303432343431303133"
is there any function in C that will make the implementation easier ? because I tried doing it with shifting but couldn't get that result.
You can do following:
Step I: Allocate memory of double the size of input and + 1 to accommodate the null character to the result string.
Step II: Iterate through the input string and, in every iteration, first copy the input[0] character to current location of result string and, in very next location of result string, copy the current processing character of input string.
Step III: Once the loop exits, add null character at the end of result string.
[Take special care of empty string because it will have nothing to encrypt]
Implementation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * encryption (const char * input) {
if ((!input) || (*input == '\0')) {
return NULL;
}
size_t len = strlen (input);
char * temp = malloc ((len * 2) + 1);
if (!temp) {
printf ("Failed to allocate memory\n");
exit (EXIT_FAILURE);
}
size_t i = 0, j = 0;
for (; input[j]; ++j) {
temp[i++] = input[0];
temp[i++] = input[j];
}
temp[i] = '\0';
return temp;
}
int main (void) {
char array[] = "356307042441013";
char * result = encryption (array);
if (result) {
printf ("result : %s\n", result);
// Free the dynamically allocated memory once done with it
free (result);
}
return 0;
}
Output:
# ./a.out
result : 333536333037303432343431303133
A cleaner, more concise solution:
#include <stdio.h>
#include <string.h>
int main()
{
char foo[] = "356307042441013";
char bar[2 * sizeof(foo) - 1];
char *src = foo, *dest = bar;
while (*src) {
*dest++ = foo[0];
*dest++ = *src++;
}
*dest = *src;
printf("foo=%s\n",foo);
printf("bar=%s\n",bar);
return 0;
}
It is better to use foo[] rather than hard-coding the length, because what if you want to change the string. If you use [] (empty brackets) the compiler will allocate exactly how many bytes you need (including the terminating null). Similarly, for bar we base the size on the size of foo by doubling it and subtracting 1 (since the terminating null does not need to be doubled).
I found a way to solve this:
int main() {
char foo[16] = "356307042441013";
char bar[2*16-1];
for (int i = 0; i < 16; i++) {
bar[2*i] = foo[i];
if (i != 16 - 1)
bar[2*i + 1] = foo[0];
}
char res[32]= "3";
strcat(res,bar);
res[30] = '\0';
printf("bar=%s\r\n",bar);
printf("begin=%s\r\n",res);
return 0;
}

Reversing a string in C without the output being null

I am trying to reverse a string (character array) using the following code, but when I attempt to print the string, the value of null. This is a homework assignment, but I am trying to learn so any help would be appreciated.
void input_reverse_string(const char* inputStr, char* reverseStr)
{
int i = 0;
int length = 0;
for (; *(inputStr++) != '\0'; i++)
{
length++;
}
while (*inputStr)
{
*reverseStr = *inputStr;
inputStr++;
reverseStr++;
}
const char* chr_ptr = &inputStr[length - 1];
printf("I see a %s\n", *chr_ptr);
*reverseStr = '\0';
printf("%d", length);
/* return reverseStr; */
}
Several things are out of order:
That's a strange way of computing the length of a string. You are using an index variable that you don't need, and incrementing 3 things at the same time, it's unneeded to say the least.
After calculating the length, and incrementing the inputStr pointer up to its end, you don't reset the pointer, so it still points to the end of the string (actually, one after the end!).
Inside the while you are advancing both pointers (inputStr and reverseStr) in the same direction, which can't possibly be right if you want to reverse the string.
The correct way to do this would be:
Compute the length of the string. Either use strlen() or do it by hand, but you really only need to increment one variable to do this. You can avoid incrementing inputStr, just use a temporary pointer.
Start from inputStr + length and walk backwards. Either use a pointer and do -- or just index the string).
Here's a working example:
void reverse_string(const char* inputStr, char* reverseStr) {
unsigned len = 0;
int i;
while (inputStr[len])
len++;
for (i = len - 1; i >= 0; i--) {
reverseStr[len - i - 1] = inputStr[i];
}
reverseStr[len] = '\0';
}
int main(void) {
char a[6] = "hello";
char b[6];
reverse_string(a, b);
puts(b);
return 0;
}
Output:
olleh

Getting garbage after reversing string in c

I am trying to reverse a string. scanf is working well but when I use fixed string then it gives garbage value. So where is the fault ?
#include<stdio.h>
#include<string.h>
int main()
{
char s[50]="Hi I Love Programming";
char rev[strlen(s)];
int i,k;
k=strlen(s);
for(i=0; i<strlen(s); i++)
{
rev[k]=s[i];
k--;
}
printf("The reverse string is: %s\n", rev);
}
Your program has two issues:
1.
char rev[strlen(s)];
You forgot to add an element for the string-terminating null character '\0'.
Use:
char rev[strlen(s) + 1];
Furthermore you also forgot to append this character at the end of the reversed string.
Use:
size_t len = strlen(s);
rev[len] = '\0';
Note, my len is the k in your provided code. I use the identifier len because it is more obvious what the intention of that object is. You can use strlen(s) because the string has the same length, doesn´t matter if it is in proper or reversed direction.
2.
k=strlen(s);
for(i=0; i<strlen(s); i++)
{
rev[k]=s[i];
k--;
}
With rev[k] you accessing memory beyond the array rev, since index counting starts at 0, not 1. Thus, the behavior is undefined.
k needs to be strlen(s) - 1.
Three things to note:
The return value of strlen() is of type size_t, so an object of type size_t is appropriate to store the string length, not int.
It is more efficient to rather calculate the string length once, not at each condition test. Use a second object to store the string length and use this object in the condition of the for loop, like i < len2.
char s[50]="Hi I Love Programming"; can be simplified to char s[]="Hi I Love Programming"; - The compiler automatically detects the amount of elements needed to store the string + the terminating null character. This safes unnecessary memory space, but also ensures that the allocated space is sufficient to hold the string with the null character.
The code can also be simplified (Online example):
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "Hi I Love Programming";
size_t len = strlen(s);
char rev[len + 1];
size_t i,j;
for(i = 0, j = (len - 1); i < len; i++, j--)
{
rev[j] = s[i];
}
rev[len] = '\0';
printf("The reverse string is: %s\n", rev);
}
Output:
The reverse string is: pgnimmargorP evoL I iH
your program is hard to understand. Here you have something much simpler (if you want to reverse the string of course)
#include <stdio.h>
#include <string.h>
char *revstr(char *str)
{
char *start = str;
char *end;
if(str && *str)
{
end = str + strlen(str) - 1;
while(start < end)
{
char tmp = *end;
*end-- = *start;
*start++ = tmp;
}
}
return str;
}
int main()
{
char s[50]="Hi I Love Programming";
printf("%s", revstr(s));
}
https://godbolt.org/z/5KX3kP

exercise 9.7 Kochan. strange output

I am working to learn C using Kochan's Programming in C 4th edition. problem 9.7 the goal is to insert a string of characters into another array. I am supposed to write a function to accomplish this. I have two problems.
When I have the algorithm print the result as it goes through the if statements, it produces the desired output, however when I change it to an %s, I only get a partial output. My hunch is that a null character is being placed where i do not want it, but I simply cannot see it.
To see what was happening, I added a printf that would track the letter and the array space it was occupying. I was surprised to see that the first letter was not 0, but was blank, and the next letter was assigned the 0. Any insight into this would be appreciated.
The funtion of interest is "insertString".
#include <stdio.h>
#include <stdbool.h>
char x[] = {"the wrong son was shot that day"};
char text[] = {"per"};
int countString (char x[])
{
int counter, z;
for (counter = 0; x[counter] != '\0'; ++counter)
z = counter+1;
return z;
}
void insertString (char text[],char x[],int n) //source, text to input, where
{
int count, clock, i = countString(text), q = countString(x);
int counter = 0;
char y[i + q];
for(count = 0; x[count] != '\0'; ++count){
if (count < n){
y[count] = x[count];
printf("%c %i", y[count], count); //The integer call is just to put a number next to the
//letter. This is where my second issue is shown.
}
else if (counter <= i){
y[count] = text[counter];
++counter;
printf("%c", y[count]);
}
else{
y[count]= x[count - counter];
printf("%c", y[count]);
}
}
printf("\n\n");
y[count-counter] = '\0';
printf("%s", y);
}
int main (void)
{
void insertString(char text[], char x[], int i);
int countString(char x[]);
int i;
insertString(text, x, 10);
return 0;
}
10 out of 10 times I post here it is because im doing something dumb, so I use SO as an absolute last resort if i am getting into the territory of just randomly trying stuff with no methodology. Thanks for your patience in advance.
Your condition is wrong in the for. It should be x[count - counter] != '\0'
In the second condition use just < to avoid overindexing. (else if (counter < i))
You put the terminating NULL char at wrong place. You should do this: y[count] = '\0'
printf inside a string routine like this is fine for debugging, but it's a poor way to write a general-purpose function because it makes it impossible to use its output for further programmatic manipulation. It can also make it difficult to reason about how the state of the function interacts in unpredictable ways with the state of the printed data.
I assume you haven't learned about dynamic memory allocation which is a prerequisite to returning strings from functions. You can inline the function logic into main or printf only at the end of the function in the meantime.
Adding to this point, a void function would need to reallocate space in the string to insert into and would be in-place. This seems likely less generally useful than allocating a new string to hold the result.
Using global variables like char x[] when there's no need is poor practice. It's better to put those strings scoped to main. Since your function can access these variables in addition to its parameters, confusion can ensue when scope and encapsulation is breached.
Use consistent formatting and avoid variable names like q that mean virtually nothing. Instead of adding comments to explain poor var names:
void insertString (char text[],char x[],int n) //source, text to input, where
You can simply name the variables exactly what they represent:
void insertString(char *dest, char *source, int add_index)
Also, now that you've mastered countString, you can abstract this by calling the builtin strlen.
Be sure to allocate enough space in buffers: char y[i + q]; should be y[i+q+1] to allow room for the null terminator '\0'.
As for the logic, I think it's easier to break into three loops without conditions instead of one loop with conditions. This makes it easier to break the problem down into the three constituent steps:
Add everything up until add_index from the dest string to the result.
Add everything in the source string to the result.
Add everything after add_index from the dest string to the result.
Using this approach, all that's left is figuring out how to map the indexes appropriately. Here it is in code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *insert_string(char *dest, char *source, int add_index) {
int source_len = strlen(source);
int dest_len = strlen(dest);
int result_size = source_len + dest_len + 1;
char *result = malloc(result_size);
for (int i = 0; i < add_index; i++) {
result[i] = dest[i];
}
for (int i = 0; i < source_len; i++) {
result[i+add_index] = source[i];
}
for (int i = add_index; i < dest_len; i++) {
result[i+add_index] = dest[i];
}
result[result_size-1] = '\0';
return result;
}
int main(void) {
char *result = insert_string("hello world", "cruel ", 6);
printf("%s\n", result);
free(result);
return 0;
}
Although this is likely for instructional purposes, these operations can be abstracted further using builtin string functions like strncpy and sprintf.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *insert_string(char *dest, char *source, int add_index) {
int result_size = strlen(dest) + strlen(source) + 1;
char *result = malloc(result_size);
char pre[add_index+1];
pre[add_index] = '\0';
strncpy(pre, dest, add_index);
sprintf(result, "%s%s%s", pre, source, dest + add_index);
return result;
}
int main(void) {
char *result = insert_string("hello world", "cruel ", 6);
printf("%s\n", result);
free(result);
return 0;
}
Doing this in-place is more straightforward. Since the result already has the prefix, you can copy the destination postfix to create a source-sized gap in the middle and then overwrite the gap using the source string. It's up to the caller to make sure that the destination buffer is large enough to hold the insertion.
#include <stdio.h>
#include <string.h>
void insert_string(char *dest, char *source, int add_index) {
int source_len = strlen(source);
int dest_len = strlen(dest);
for (int i = add_index; i < dest_len; i++) {
dest[i+add_index] = dest[i];
}
for (int i = 0; i < source_len; i++) {
dest[i+add_index] = source[i];
}
}
int main(void) {
// allocate extra space in the string to hold the insertion
char greeting[32] = "hello world";
insert_string(greeting, "cruel ", 6);
printf("%s\n", greeting);
return 0;
}
A note of caution: none of these functions handle errors at all, so they're unsafe. Correct functions should check that the add_index falls within the bounds of the dest string. This is an exercise for the reader.
The original exercise is here:
Your function is not doing it. You need to insert the string into another string not to create a new one with both mixed. You can do it this way of course and then copy it into the original one - but it is the most uneficient way to archive it (memory & timewise).
Use the correct types.
size_t mystrlen(const char *str)
{
const char *end = str;
while(*end++);
return end - str - 1;
}
char *strinsert(char *dest, size_t pos, const char *istr)
{
char *temp = dest, *work;
size_t ilen = mystrlen(istr);
size_t nmove;
while(*temp) temp++;
nmove = temp - dest - pos + 1;
work = temp;
temp += ilen;
while(nmove--) *temp-- = *work--;
work = dest + pos;
while(*istr) *work++ = *istr++;
return dest;
}
int main()
{
char dest[128] = "0123456789012345678901234567890123456789";
printf("%s", strinsert(dest, 7, "ABCD"));
}
https://godbolt.org/z/KMnLU2

Populating a buffer from the return of a method fails... ANSI C

The code I have is quite simple in one method I have this:
// This line has an Intellisense Error: Initialization with {...} expected for aggregate object
char str[] = GetBuffer(); // x 64 will give us 512 (sector sized buffer) ;
The GetBuffer metod is this:
char * GetBuffer(void)
{
int idx = 0;
int offset = 0;
char *buffer[512];
for(idx =0; idx < 64; idx ++)
{
// This line has an Itellisense Error: "Expected Expression"
buffer[offset + idx] = {"E","R","A","S","E","D"," ", " "};
offset += 8;
}
return *buffer;
}
Any ideas what's wrong with this?
All I am trying to do - is populate a buffer with 512 bytes which contain the following string repeated: "ERASED " This is ANSI C (not C++) and it has been so long since I coded in ANSI C - please help and be kind!
Using Visual Studio 2012
EDIT 1
Ok lots of things have been fixed thanks to you guys - but no full answer yet.
The str buffer holds 528 characters and not 512 and contains a lot of ERASED as expected but ends with
ýýýý««««««««îþîþ
Any ideas with this? And Oh boy I have a great deal of pure C reading to do - I have forgotten way too much!
You can't initialize an array with the return value from a function.
You could use a pointer instead of an array:
char *str = GetBuffer();
Or you could use strcpy() or a relative — but there are buffer overflow risks:
char str[512];
strcpy(str, GetBuffer());
Your GetBuffer() function also has a lot of problems.
char *GetBuffer(void)
{
int idx = 0;
int offset = 0;
char *buffer[512];
This should probably be char buffer[512];, but...
for(idx =0; idx < 64; idx ++)
{
// This line has an Itellisense Error: "Expected Expression"
buffer[offset + idx] = {"E","R","A","S","E","D"," ", " "};
You can't set arrays like this. And you needed double quotes because of the char *buffer[512] problem.
offset += 8;
}
return *buffer;
}
And you should not return a local variable — it is destroyed when the function returns so it can't be used afterwards.
You might write:
char *GetBuffer(void)
{
char *buffer = malloc(257);
if (buffer != 0)
{
int idx;
for (idx = 0; idx < 256; idx += 8)
strcpy(buffer+idx, "ERASED ");
}
return buffer;
}
There's a small layer of obfuscation going on with the hard-coded lengths and limits; they're correct, but the interconnections between the sizes are not obvious — and ideally, they should be:
strlen("ERASED ") == 8
256 = 32 * strlen("ERASED ")
257 = 32 * strlen("ERASED ") + 1 (the one is for the terminal null)
And then the calling code might be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *str = GetBuffer();
if (str != 0)
{
printf("<<%s>>\n", str);
free(str);
}
return(0);
}
there is problem with your buffer creation. you'd malloc such that it's not reclaimed by the function invoke routine. Second, you can't do assignment like the line you encountered a Itellisense error.
You can use this:
#include "stdlib.h"
char * GetBuffer(void)
{
int i = 0, idx = 0;
const char * cstr_init = "ERASED ";
char *buffer = (char*)malloc(512);
for (idx = 0; idx < 512; idx+=8) {
for (i = 0; i < 8; i++) {
buffer[idx+i] = cstr_init[i];
}
}
return buffer;
}
There are several things wrong here.
In C, a character array can be initialized with an initializer list or a string literal. You cannot use the return value from a function to initialize the array. So
char str[] = GetBuffer();
will not work.
Also, char* buffer [512] is an array of 512 pointers to char, i.e., an array of 512 strings. buffer [offset + idx] would be one pointer to char. It can hold only one string, but you are trying to assign eight strings to it: "E", "R", etc. If you mean those to be chars and not strings, use single quotes: 'E', etc. However, even that won't work unless you allocate memory to the pointer so that it can hold the string.
As written, the array of pointers is allocated on the stack, so it goes out of scope when the function terminates. return *buffer would return the first string in the array of strings, but that's a local variable, so you're returning the dereferenced value of a pointer that is no longer in scope.
I think a simpler way to accomplish your goal is this:
char str [512] = {'\0'};
for (int i = 0; i < 511; i += 7)
strcat (str + i, "ERASED ");
It's not very general, but it does what you want.
Edited to reflect Jonathan Leffler's comment that strcat (str, "ERASED "), which is what I originally had, is inefficient.

Resources