tbh I thought it wouldn't be hard to learn C seeing as I already know several other languages, but I'm having trouble with my code, and I can't seem to figure out how to fix these errors. I specialize in Python, so this is much different because of all the specifications for types, pointers, etc. Anyway, here's the code below, sorry, I would paste the error, but it won't allow me to copy paste. I was using some print functions and found the error to be coming from line 9, "*returnStr += *str";. Thanks in advance for any help.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
char *multiplyString(const char *str, int num){
char *returnStr = "";
for (int i = 0; i < num; i++){
*returnStr += *str;
}
return returnStr;
}
int main(void){
bool asking = true;
int height;
const char *symbol = "#";
while (asking == true){
height = get_int("How tall should the pyramid be? pick a number between 1 and 8: ");
if (8 >= height && height >= 1){
asking = false;
}
}
for (int i=1; i<=height; i++){
printf("%s %s\n", strcat(multiplyString(" ", height-i), multiplyString(symbol, i)), multiplyString(symbol, i));
}
}
Change multiplyString() to the following
char *multiplyString(const char *str, int num) {
// + 1 for null-terminator
char *returnStr = calloc(sizeof(*returnStr), strlen(str)*num + 1);
for (int i = 0; i < num; i++) {
strcat(returnStr, str);
}
return returnStr;
}
You were attempting to modify a string literal, which is forbidden in C. Secondly, += is not string concatenation in C; rather, it was trying to perform integer addition on the first character of returnStr.
To fix this, you dynamically allocate the proper amount of memory using calloc() (which also initializes the memory to 0, which is necessary for strcat()). Then, in each iteration, append the string using strcat() to the end of the new string.
Remember to free the strings returned by this function later in the program, as they are dynamically allocated.
Two problems:
First of all, returnStr is pointing to a string literal, which is really an array of read only characters. In this case an array of only a single character, being the string terminator '\0'
Secondly, *returnStr += *str; makes no sense. It's the same as returnStr[0] = returnStr[0] + str[0]. And since the destination (returnStr[0]) is a string literal, attempting to write to it leads to undefined behavior
If you want to create a new string containing num copies of str, then you need to create a new string containing at least num * strlen(str) + 1 characters, the +1 for the terminator. Then you need to use strcat to concatenate into that new string.
Also if you allocate memory dynamically (with e.g. malloc) then you need to make sure that the first element is initialized to the string terminator.
Related
#include <stdio.h>
void append(char* s, char n);
void splitstr(char* string);
int main()
{
splitstr("COMPUTE 1-1");
printf("\n");
splitstr("COMPUTE 1+1");
printf("\n");
splitstr("COMPUTE 1*1");
return 0;
}
void append(char* s, char ch) {
while(*s != '\0'){
s = s + 1;
}
*s = ch;
s = s + 1;
*s = '\0';
}
void splitstr(char* string){
int count = 1;
char* expression = "";
while(*string != '\0'){
if(count > 8){
append(expression, *string);
string = string + 1;
count = count + 1;
}else{
string = string + 1;
count = count + 1;
}
}
printf("%s",expression);
}
Example Input and Output:
Input: COMPUTE 1+1
Output: 1+1
Input: COMPUTE 2-6
Output: 2-6
Originally, this code does not include stdio.h (I am doing this for testing on an online C compiler) because I am building an OS from scratch so I need to write all the functions by myself. I think the problem might be in the append function but I cannot find it.
instead of
char* expression = "";
do
char[MAX_expression_length+1] expression;
or use realloc in the append function
I think this line is the culprit:
append(expression, *string);
Notice how expression is declared:
char* expression = "";
In other words, expression consists of one byte, a single \0. Right away, we can see that append() won't work like you want it to--the while loop will never run, because *s is already \0.
But beyond that, the segfault likely happens at the bottom of append(). After the while loop, you unconditionally increment s and then write to the location it now points to. The problem is that this is a location that has never been allocated (since s is a reference to splitstr()'s expression, which is a single byte long). Furthermore, because expression is declared as a string constant, depending on your platform it may be placed in an area of memory marked read-only. Consequently, this is an attempt to write into memory that may not actually belong to the process and may also not be writable, raising the fault.
expression points to a string literal, and trying to modify a string literal leads to undefined behavior.
You need to define expression as an array of char large enough to store your final result:
char expression[strlen(string)+1]; // VLA
Since your result isn’t going to be any longer than the source string, this should be sufficient (provided your implementation supports VLAs).
I need help with char array. I want to create a n-lenght array and initialize its values, but after malloc() function the array is longer then n*sizeof(char), and the content of array isnt only chars which I assign... In array is few random chars and I dont know how to solve that... I need that part of code for one project for exam in school, and I have to finish by Sunday... Please help :P
#include<stdlib.h>
#include<stdio.h>
int main(){
char *text;
int n = 10;
int i;
if((text = (char*) malloc((n)*sizeof(char))) == NULL){
fprintf(stderr, "allocation error");
}
for(i = 0; i < n; i++){
//text[i] = 'A';
strcat(text,"A");
}
int test = strlen(text);
printf("\n%d\n", test);
puts(text);
free(text);
return 0;
}
Well before using strcat make
text[0]=0;
strcat expects null terminated char array for the first argument also.
From standard 7.24.3.1
#include <string.h>
char *strcat(char * restrict s1,
const char * restrict s2);
The strcat function appends a copy of the string pointed to by s2
(including the terminating null character) to the end of the string
pointed to by s1. The initial character of s2 overwrites the null
character at the end of s1.
How do you think strcat will know where the first string ends if you don't
put a \0 in s1.
Also don't forget to allocate an extra byte for the \0 character. Otherwise you are writing past what you have allocated for. This is again undefined behavior.
And earlier you had undefined behavior.
Note:
You should check the return value of malloc to know whether the malloc invocation was successful or not.
Casting the return value of malloc is not needed. Conversion from void* to relevant pointer is done implicitly in this case.
strlen returns size_t not int. printf("%zu",strlen(text))
To start with, you're way of using malloc in
text = (char*) malloc((n)*sizeof(char)
is not ideal. You can change that to
text = malloc(n * sizeof *text); // Don't cast and using *text is straighforward and easy.
So the statement could be
if(NULL == (text = (char*) malloc((n)*sizeof(char))){
fprintf(stderr, "allocation error");
}
But the actual problem lies in
for(i = 0; i < n; i++){
//text[i] = 'A';
strcat(text,"A");
}
The strcat documentation says
dest − This is pointer to the destination array, which should contain
a C string, and should be large enough to contain the concatenated
resulting string.
Just to point out that the above method is flawed, you just need to consider that the C string "A" actually contains two characters in it, A and the terminating \0(the null character). In this case, when i is n-2, you have out of bounds access or buffer overrun1. If you wanted to fill the entire text array with A, you could have done
for(i = 0; i < n; i++){
// Note for n length, you can store n-1 chars plus terminating null
text[i]=(n-2)==i?'A':'\0'; // n-2 because, the count starts from zero
}
//Then print the null terminated string
printf("Filled string : %s\n",text); // You're all good :-)
Note: Use a tool like valgrind to find memory leaks & out of bound memory accesses.
I am trying to write a program that will conjugate a verb in multiple forms.
So I write a function that will allow me to get the part that is kepted and conjugate it. Fixed rule : whole word except last 2 chars.
I am used to OO, and I can't seem to make it work, while it seems a basic program.
I obtain something with weird : here is a screen at the end of the execution, that will be more explicit
I think I missed a little something in my course (probably in the char[] part...), that has a huge impact, but I can't seem to find it.
I am opened to all observations on my code, since I am beginning, and I prefer going on a solid basis right now, better that later.
Here is the code
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
void RacineVerbe(char verbeEntier[], char dest[]);
int myStrLen(char *s);
int main()
{
char *string;
char *racine;
string = (char*)malloc(200*sizeof(char));
racine = (char*)malloc(200*sizeof(char));
printf("Quel verbe?\n");
scanf("%s", string);
RacineVerbe(string, racine);
printf("%s", racine);
printf("%sASSE\n", racine);
printf("%sASSES\n", racine);
printf("%sAT\n", racine);
printf("%sASSIONS\n", racine);
printf("%sASSIEZ\n", racine);
printf("%sASSENT\n", racine);
return 0;
}
void RacineVerbe(char verbeEntier[], char dest[]){
int i;
int l = myStrLen(verbeEntier);
for( i = 0; i < l -2 ; i++){
dest[i] = verbeEntier[i];
}
dest[i+1] = "\0";
}
int myStrLen(char *s){
int i = 0;
while(*s++)i++;
return i;
}
The problem is in you RacineVerbe because you assigned string literal to single character (not a poitner to characters).
In that situation, string literal returns you the address where it is in memory and you assigned to dest[i+i] LSB byte of that address and it may be or may not be visible character. I can assure, your compiler gave you at least warning for that.
Second problem is where you did assignment. You should do it to dest[i] as i was last time incremented in for loop before check failed and therefore i already points to place where 0 should be written.
void RacineVerbe(char verbeEntier[], char dest[]){
int i;
int l = myStrLen(verbeEntier);
for( i = 0; i < l -2 ; i++){
dest[i] = verbeEntier[i];
}
dest[i] = 0; //This line was rewritten.
}
And as already mentioned, try to NOT cast return result of malloc.
You invoked UB when you wrote dest[i+1] = "\0"; since dest[i+1] expects a char and you assigned "\0" into it, which is a string literal. Replace it with '\0'
Note that string = (char*)malloc(200*sizeof(char)); ---> string = malloc(200); since casting is not needed in malloc in C, and considered bad (as you can see here) and also sizeof(char) is, by definition, 1
I tried to reverse a string using c but the following snippet is not working and the output is not printed as expected,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverse(const char * orig);
int main(void)
{
char * string = "REVERSE";
reverse(string);
return 0;
}
void reverse(const char * orig)
{
int i = 0, j=strlen(orig);
int k = j;
printf("The string is : %s \n",orig);
char * new = (char *)malloc((j*sizeof(char))+1);
while(j > 0)
{
new[i++] = orig[j--];
}
new[k+1] = '\0';
printf("\n The Reversed string is : %s",new);
}
In the first loop while (j > 0), j is strlen(orig), thus orig[j--] is the string terminating '\0'.
With new[i++] = orig[j--]; where i == 0, the first character of new indicated the end of string, and thus the resulting string is always empty.
You may want to change it into new[i++] = orig[--j];.
You also need to change new[k+1] = '\0'; into new[k] = '\0'; to terminate the output string new correctly.
Algorithmic errors
j should start at strlen(orig)-1, otherwise you are copying the string terminator in the first position of new, thus making it a zero-length string;
the loop condition should read j>=0 - you do want to copy the first character of the target string;
you must manually terminate new with a NUL character;
Language usage errors
you are mallocing but not freeing - thus your reverse function is leaking memory;
the conversion from string literal to non-const char * (in main) is deprecated;
Stylistic warnings
sizeof(char) is 1 by definition, so it's useless to include it in the calculation;
although a valid variable name in C, new is a reserved keyword in C++, so you may want to use a different name (often C code ends up mixed in C++ code and/or editors use the same highlighter definition thus confusing matters).
The problem:
is that at the first iteration orig[j=strlen(orig)]` is the string terminator. You are placing the terminator at the beginning of the new string.
Change to
new[i++] = orig[--j];
live
I have written a method in C that removes characters from a string
char* removeChars(char input[], char remove[])
{
int src, dst = 0;
int size = strlen(input);
bool flags[128];
char output[18]; // <- This should be output[size]!
int i;
for(i=0; i<128; i++) {
flags[i] = false;
}
int j=0;
while(remove[j] != '\0') {
flags[remove[j]] = true;
j++;
}
for(src=0; src<size; src++) {
if(flags[input[src]] != true) {
output[dst++] = input[src];
}
}
return output;
}
One of the issues that I am having is that when I attempt to set the size of the output array using size (i.e. char output[size]), The output array appears to always have zero elements. It only seems to work when I specify a specific size (like 18). Should I be using strcpy or malloc instead? If so, how should it be done?
char *output = malloc(sizeof(char) * (size+1));
If you want memory to be dynamically allocated using size.
Once you are done using this memory please free it.
free(output);
Your program has undefined behaviour because you are returning pointer to the first element of a local array that in general case will be destroyed after exiting the function.
So you have to allocate the array in the heap dynamically.
The other problem is that you do not append the output string with the terminating zero.
The function woild look simpler if you would remove characters in the source string that is "in place". In this case there is no any need in an additional array.
Also you could use standard function strchr declared in header <string.h> that to determine whether a given character in the source string is present in the string that contains characters to be removed.