I have a dynamically sized CHARS array, I'm trying to print the string, using pointers.
I tried something like this:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main(){
char *str = NULL;
int size = 0;
int c, i;
printf("Please enter your command\n");
while((c = getchar()) != EOF)
{
str = (char *)realloc(str, size + 1);
str[size++] = c;
}
str = (char *)realloc(str, size + 1);
str[size] = '\0';
free(str);
printf("\nThe size is %d\n", size);
/* here I want to print the string */
for(i = *str; i!='\0'; i++){
printf("%c", *str+i);
}
return 0;
}
This code does not print the string. The topic of using pointers is not really clear to me, so I think there is my mistake.
You deallocated early allocated memory
free(str);
So after this statement the pointer str is invalid and accessing memory using the pointer invokes undefined behavior. You need to free the memory when the allocated character array will not be required any more.
This for loop
/* here I want to print the string */
for(i = *str; i!='\0'; i++){
printf("%c", *str+i);
}
does not make sense. In this for loop the variable i that stores the code of the first character of the string stored in the dynamically allocated array is incremented. For example if the first character of the string is 'A' that is in ASCII 65 then after the first iteration it will be equal to 66 that corresponds to the character 'B'. And the expression *str + i will look like 'A' + 'B' that is the same as 65 + 66.
If you are going to outputted the stored string using a pointer then you should write for example
/* here I want to print the string */
for ( const char *p = str; *p != '\0'; ++p ){
printf("%c", *p);
}
putchar( '\n' );
You need to free the memory when you do not need it anymore.
Move free(str) to the end of main.
Also printf("%c", *str+i); is wrong. You need to printf("%c", *(str+i));
You do not check the result of realloc.
char *tmp;
tmp = realloc(str, size + 1);
if(tmp)
{
str = tmp;
str[size++] = c;
}
else
{
/* handle error */
}
+++ more issues so I will post the working code:
int main(void){
char *str = NULL;
size_t size = 0;
int c;
size_t i;
printf("Please enter your command\n");
while((c = getchar()) != EOF)
{
char *tmp;
tmp = realloc(str, size + 2);
if(tmp)
{
str = tmp;
str[size++] = c;
}
else
{
return 1;
}
}
str[size] = '\0';
printf("\nThe size is %zu\n", size);
/* here I want to print the string */
for(i = 0; str[i]; i++){
printf("%c", *(str+i));
}
free(str);
return 0;
}
Related
Here I have code that inputs from stdin a stream of characters into an array. It then converts that array to a 2d array. Then it changes that array from row column order to column row order. Then it prints out the new array creating a Caesar shift encryption. The issue I am having is that my array is starting to input characters into the array with the second user typed character and I am not sure why.
For Example, if I type "Hello" into the console, only "ello" is put into the array.
Any thoughts? Thanks!
//
// main.c
// Caesar Block Cypher
//
// Created by Jacob Byerline on 10/20/18.
// Copyright © 2018 Jacob Byerline. All rights reserved.
//
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int main(void){
//The size is extended by the input with the value of the provisional
char *str;
int inputChar;
int i, j;
size_t size = 0;
size_t len = 0;
printf("input string : ");
inputChar = getchar();
str = realloc(NULL, sizeof(char)*size);//size is start size
if(!str)return *str;
while(EOF!=(inputChar=fgetc(stdin)) && inputChar != '\n'){
if(isalpha(inputChar)){
str[len++]=inputChar;
if(len==size){
str = realloc(str, sizeof(char)*(size+=16));
if(!str)return *str;
}
}
}
str[len++]='\0';
int squareOfLen = sqrt(len);
int twoDimensionalArraySize = squareOfLen + 1;
//printf("%lu \n", len);
//printf("%d \n", squareOfLen);
//printf("%d \n", twoDimensionalArraySize);
char twoDstr[twoDimensionalArraySize][twoDimensionalArraySize];
char FINALtwoDstr[twoDimensionalArraySize][twoDimensionalArraySize];
memcpy(twoDstr, str, twoDimensionalArraySize * 2 * sizeof(int));
for(i=0; i<twoDimensionalArraySize; i++){
for(j=0; j<twoDimensionalArraySize; j++){
printf("2D Array[%d][%d] = %c\n",i,j,twoDstr[i][j]);
}
}
for(i=0; i<twoDimensionalArraySize; i++){
for(j=0; j<twoDimensionalArraySize; j++){
FINALtwoDstr[i][j] = twoDstr[j][i];
//printf("2D Array[%d][%d] = %c\n",i,j,FINALtwoDstr[i][j]);
printf("%c",FINALtwoDstr[i][j]);
}
}
printf("\n");
return 0;
}
Remove
inputChar = getchar();
This is taking up 'H' from your input stream.
See here https://ideone.com/ZwT9Iq
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int main(void){
//The size is extended by the input with the value of the provisional
char *str;
int inputChar;
int i, j;
size_t size = 0;
size_t len = 0;
printf("input string : ");
//inputChar = getchar();
str = realloc(NULL, sizeof(char)*size);//size is start size
if(!str)return *str;
while(EOF!=(inputChar=fgetc(stdin)) && inputChar != '\n'){
if(isalpha(inputChar)){
str[len++]=inputChar;
if(len==size){
str = realloc(str, sizeof(char)*(size+=16));
if(!str)return *str;
}
printf("%c", inputChar);
}
}
printf("\n");
str[len]='\0';
int squareOfLen = sqrt(len);
int twoDimensionalArraySize = squareOfLen + 1;
//printf("%lu \n", len);
//printf("%d \n", squareOfLen);
//printf("%d \n", twoDimensionalArraySize);
char twoDstr[twoDimensionalArraySize][twoDimensionalArraySize];
char FINALtwoDstr[twoDimensionalArraySize][twoDimensionalArraySize];
memcpy(twoDstr, str, twoDimensionalArraySize * 2 * sizeof(int));
for(i=0; i<twoDimensionalArraySize; i++){
for(j=0; j<twoDimensionalArraySize; j++){
printf("2D Array[%d][%d] = %c\n",i,j,twoDstr[i][j]);
}
}
for(i=0; i<twoDimensionalArraySize; i++){
for(j=0; j<twoDimensionalArraySize; j++){
FINALtwoDstr[i][j] = twoDstr[j][i];
//printf("2D Array[%d][%d] = %c\n",i,j,FINALtwoDstr[i][j]);
printf("%c",FINALtwoDstr[i][j]);
}
}
printf("\n");
return 0;
}
output
Hleol
Ignoring allocation and check for alpha-ness, you do this:
inputChar = getchar(); // Read first char
while (EOF != (inputChar=fgetc(stdin)) // read further chars
&& inputChar != '\n') {
str[len++]=inputChar;
}
That means that the first character is consumed, but never stored. Instead, you could do this:
inputChar = getchar(); // Read first char
while (inputChar != EOF && inputChar != '\n') {
str[len++]=inputChar;
inputChar=fgetc(stdin) // read further chars
}
But there are other issues with your code:
You start with an allocation of zero bytes, because size is 0;
You should allocate before you store, otherwise you write beyond the end of the buffer;
When you add the null terminator, you probably shouldn't increase len, because the '\0' isn't part of the locical length of the string, even if you have to allocate space for it, which you don't in all cases;
The square of len is len * len, not sqrt(len): That's the square root;
You square the dimension twice: If len is 3, you want an 3×3 array, but you try to allocate a 9×9 array on the stack;
You can't copy len*len * 2 * sizeof(int) bytes from str, which has only len bytes.
There's probably more in the last part; I haven't looked too closely.
I'm trying to remove consecutive repeated characters from a given string.
Example:
bssdffFdcrrrtttii ***#
output is supposed to be:
bsdfFdcrti *#
This code doesn't work and only prints the first char (b), I want to learn about my mistake.
when I'm doing a printf test, it works but not for spaces.
I think the problem might be with the new char array.
void Ex6() {
char* string[80];
scanf("%s", &string);
puts(removeDup(string));
}
char* removeDup(char *string) {
int i, c = 0;
char* newString[80];
for (i = 0; i < strlen(string); i++) {
if (string[i] != string[i + 1]) {
newString[c++] = string[i];
}
}
return newString;
}
There are several problems with your program:
The declaration of newString should be char newString[80], i.e., an array of characters and not an array of pointers-to-characters, and likewise for the declaration in Ex6.
The call to scanf should then be scanf("%s", string), since string is already the address of an array of characters, but...
Use fgets to read a string from the user to ensure that you read whitespace, if it's important, and that the buffer is not exceeded.
newString is allocated on the stack and so should not be returned to the caller. It is better to do a char *newString = strdup(string), or, slightly less sloppy, char *newString = malloc(strlen(string)+1), which will call malloc for a block of memory sufficient to hold the original string, and thus the version without duplicates -- the comments rightly point out that this could be optimized. In principle, the caller, i.e., Ex6, must free the returned pointer to avoid a memory leak but it hardly matters in such a short program.
The result needs a null terminator: newString[c] = '\0'.
Otherwise, the removeDup function seems to work correctly.
So, putting all of that together:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* removeDup(const char *string)
{
size_t i, c = 0;
size_t string_len = strlen(string);
char *newString = malloc(string_len + 1);
for (i = 0; i < string_len; i++) {
if (string[i] != string[i + 1]) {
newString[c++] = string[i];
}
}
newString[c] = '\0';
return newString;
}
#define MAX_STRING_LEN 80
void Ex6() {
char string[MAX_STRING_LEN];
char* result;
if (fgets(string, MAX_STRING_LEN, stdin) != NULL) {
result = removeDup(string);
printf("%s", result);
free(result);
}
}
Finally, I agree with #tadman's comment. Since the input string must anyway be traversed to calculate the length, we may as well optimize the size of the result string:
char* removeDup(const char *string)
{
size_t i, c = 0;
char *newString;
for (i = 0; string[i] != '\0'; i++)
c += (string[i] != string[i + 1]);
newString = malloc(c + 1);
for (i = c = 0; string[i] != '\0'; i++) {
if (string[i] != string[i + 1]) {
newString[c++] = string[i];
}
}
newString[c] = '\0';
return newString;
}
There are quite a few issues in your program. It wouldn't even compile let alone run. Also, the most problematic issue is that you are returning a pointer to a local variable from a function that ceases its scope upon completion. A simplified version of your program is as follows:
void Ex6()
{
char string[80];
scanf("%s", string);
int i, c = 0;
char newString[80];
for (i = 0; i < strlen(string); i++) {
if (string[i] != string[i + 1]) {
newString[c++] = string[i];
}
}
newString[c] = '\0';
puts(newString);
}
You can do it with O(n) time and O(1) space, by modifying existing string:
#include <stdio.h>
char* removeDup(char* input) {
char* newTail = input, *oldTail = input;
while (*oldTail) {
if (*newTail == *oldTail) {
++oldTail;
} else {
*++newTail = *oldTail++;
}
}
return newTail;
}
int main() {
char string[] = "bssdffFdcrrrtttii ***#";
char* newEnd = removeDup(string);
char* tmp = string;
while (tmp != newEnd) {
printf("%c", *tmp++);
}
//Print the last char if string had any duplicates
if(*tmp) {
printf("%c", *tmp++);
}
return 0;
}
I have written a program to take input and dynamically allocate memory using realloc(), however there seems to be an error because if I print the final string char by char I seem to have 2 empty bytes at the end, I am sure this is going to be something silly but I have spent some time trying to discover the cause and have failed so hope to learn something here.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int count = 0;
char *str;
char tmp;
str = malloc(sizeof(char));
while (tmp != '\n') {
tmp = getchar();
str = realloc(str, (count + 1) * sizeof(char));
*(str + count) = tmp;
count += 1;
}
*(str + count) = '\0';
puts(str);
// This is just to try and see what was happening
for (int i = 0; i <= count; i++)
printf("str[%d] = %c\n", i, str[i]);
free(str);
str = NULL;
return EXIT_SUCCESS;
}
Four things to mention here.
while(tmp != '\n') is reading uninitialised automatic local variable value without initialization. It invokes undefined behaviour.
str = realloc(str, (count + 0x01) * sizeof(char)); is very bad, if realloc() fails, you'll lose the actual pointer, too. Always use a temporary pointer to hold the return value from realloc() and after proper error check, assign it back to the main pointer.
sizeof(char) is guaranteed to be 1. You don't need to use as a multiplier. It's redundant.
The for loop condition, should be i < count otherwise, you'll run into off-by-one error. C uses 0 based indexing.
That said,
You should always check for the success of the return vale of realloc() and family of functions for success before using the returned pointer.
getchar() returns an int. You should change the type of tmp to int tmp = 0;
This loop should look at least like
for(int i = 0; i < count; i++)
^^^
printf("str[%d] = %c\n", i, str[i]);
Or it would be better to write
for(int i = 0; str[i]; i++)
printf("str[%d] = %c\n", i, str[i]);
Or
int i = 0;
for ( char *p = str; *p; ++p )
printf( "str[%d] = %c\n", i++, *p );
And change these statements
while(tmp != '\n') {
tmp = getchar();
to
while ( ( tmp = getchar() ) != EOF && tmp != '\n' )
Also it would be more safe instead of this statement
str = realloc(str, (count + 0x01) * sizeof(char));
to write
char *p = realloc(str, (count + 0x01) * sizeof(char));
if ( !p ) break;
else str = p;
Apart from the uninitialized variable access, the two “empty characters” are:
a newline, since you check for \n before you read and store the next character, and
a character in uninitialized memory since you’re incorrectly looping while i <= count and not while i < count.
Use a for (;;) (infinite loop) and check if (tmp == '\n') { break; } immediately after getchar() to avoid both the uninitialized variable access and trailing newline.
I'm trying to brush up on my C/C++ and I seem to have forgotten how to properly manipulate char arrays.
Code:
#include <iostream>
#include <string.h>
void reverse(char* str)
{
int numChar = strlen(str);
char *reversed = (char*)malloc(sizeof(char) * (numChar + 1));
int i = numChar;
int j = 0;
while(i >= 0)
{
reversed[j] = str[i];
j++;
i--;
printf("%c", reversed[j]);
}
printf("%s", reversed);
}
int main()
{
char* str;
strcpy(str, "apple\0");
reverse(str);
return 0;
}
I'm very certain I'm not doing what I intend to with reversed[j] = str[i] as reversed comes out empty. What's the correct way to go about this?
From first glance, In main(), memory has to be allocated to character pointer str before referencing it in strcpy
int main()
{
char* str = malloc(6) or use char str[6];
// or char *str = "apple"; is sufficient, strcpy is not required in this case
strcpy(str, "apple\0");
reverse(str);
return 0;
}
Another one :
In reverse() function, you will have to increment j after printing
while(i >= 0)
{
reversed[j] = str[i];
printf("%c", reversed[j]);
j++; //Moved here
i--;
}
reversed[j] = '\0' //Null termination
printf("\n %s", reversed);
or only the below two statements would be sufficient enough to post increment j and decrement i
reversed[j] = str[i--];
printf("%c", reversed[j++]);
Since you start with i being the strlen of the input string (e.g. HAHA -> 4), you start copying at haha[4], which is the null byte at the end of the string. IOW you just null terminated your output right at the start. Try setting i to numChar - 1.
(After fixing the problem Santosh A mentioned)
And then, make sure you null terminate the result!
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the function to replace string in C?
I am trying to replace a certain character in my string with multiple characters. Here is an example of what I am trying to do.
Say I have the string "aaabaa"
I want to replace all occurrences of the character "b" with 5 "c"s.
So when I am done, "aaabaa" becomes "aaacccccaa"
I have written the following code:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[20] = "aaabaa";
int i, j;
for (i=0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
for (j=0; j<5; j++)
{
s[i+j] = 'c';
}
}
}
printf("%s\n", s);
}
My output from this function is "aaaccccc". It appears that it just overwrites the last two a's with the c's. Is there any way I would have it so that these last couple of a's dont get overwritten?
If you want to do this in general, without worrying about trying to size your buffers, you should malloc a new string just large enough to hold the result:
/* return a new string with every instance of ch replaced by repl */
char *replace(const char *s, char ch, const char *repl) {
int count = 0;
const char *t;
for(t=s; *t; t++)
count += (*t == ch);
size_t rlen = strlen(repl);
char *res = malloc(strlen(s) + (rlen-1)*count + 1);
char *ptr = res;
for(t=s; *t; t++) {
if(*t == ch) {
memcpy(ptr, repl, rlen);
ptr += rlen;
} else {
*ptr++ = *t;
}
}
*ptr = 0;
return res;
}
Usage:
int main() {
char *s = replace("aaabaa", 'b', "ccccc");
printf("%s\n", s);
free(s);
return 0;
}
Your problem is that you replace the "ccccc" into the original string thus overwriting the remaining characters after what you wish to replace... You should copy into a new string and keep track of two indices - one in each.
And be happy that you declared char s[20] larger than the size of your original string plus the replace values, as otherwise you'd have created a buffer overflow vulnerability in your critical login system :-)
Cheers,
It is necessary to declare a second char array. In below code it just copies content of array s to s1 when condition fails.
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[20] = "aaabaa";
char s1[1024];
int i, j, n;
for (i=0, n = 0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
for (j=0; j<5; j++)
{
s1[n] = 'c';
n++;
}
}
else
{
s1[n] = s[i];
n++;
}
}
s1[n] = '\0';
printf("%s\n", s1);
}
You can use a different variable
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[20] = "aaabaa";
char temp[20]="";
int i, j,k;
k=0;
for (i=0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
for (j=0; j<5; j++)
{
temp[k] = 'c';
k++;
}
}
else
{
temp[k]=s[i];
k++
}
}
printf("%s\n", temp);
}
#include <stdio.h>
#include <string.h>
int main(void)
{
char temp[20];
char s[20] = "aaabaa";
int i, j;
for (i=0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
strcpy(temp,s[i+1]); //copy rest of the string in this case 'aa'
for (j=0; j<5; j++)
{
s[i+j] = 'c';
}
s[i+j] = '\0'; // here we get s = "aaaccccc"
strcat(s,temp); // concat rest of the string (temp = "aa") after job is done.
// to this point s becomes s = "aaacccccaa"
}
}
printf("%s\n", s); //s = "aaacccccaa".
}
here we are using a buffer (temp) to store the rest of the string after our to be replaced character.
after the replacement is done we append it to the end.
so we get s = "aaacccccaa"
Well, if you're going to dynamically allocate the array, you will probably have to allocate a second array. This is necessary because your string s only has a fixed amount of memory allocated.
So, instead of tryig to overwrite the characters in your for loop, I would suggest incrementing a counter that told you how big your new array has to be. Your counter should start off as the size of your original string and increment by 4 each time an instance of 'b' is found. You should then be able to write a function that appropriately copies the modified string over to a new char buffer of size[counter], inserting 5 c's every time a 'b' is being found.
Use this function :
char *replace(char *st, char *orig, char *repl) {
static char buffer[4096];
char *ch;
if (!(ch = strstr(st, orig)))
return st;
strncpy(buffer, st, ch-st);
buffer[ch-st] = 0;
sprintf(buffer+(ch-st), "%s%s", repl, ch+strlen(orig));
return buffer;
}
for your case : printf("%s\n", replace(s,"b","ccccc"));