Strcat adding "blank space" to array - c

I have a function that is reading from a file for package names and their directories. I have setup a variable to catch one item before the other (they are separated by a comma). When I append to my string it seems to add it just fine. However, when I go to realloc the string (compress it down to its actual size) it owns retains half of the characters.
When I used to a for loop to test it, there are empty characters being projected between each character. So I have a test work "duck" when I print it as a string it will write "duck" however if it iterate over it, it will go "d" " " "u" " " "c"
while(1)
{
char c = fgetc(db);
actual_file_size++;
if(c == EOF)
{
//pkg_install_dir = realloc(pkg_install_dir, (sizeof(pkg_install_dir) + 2));
//printf("The install dir is: %s\n", pkg_install_dir);
break;
}
if(is_pkg_name) {
printf("Chracter being added to pkg_name: %c\n", c);
strcat(pkg_name, &c);
} else {
strcat(pkg_install_dir, &c);
}
if(c == ',')
{
printf("Actual file size int is: %d\n", actual_file_size);
printf("Package name before realloc: %s\n", pkg_name);
for(int i = 0; i < 5; i++)
{
printf("%c\n", pkg_name[i]);
}
pkg_name = realloc(pkg_name, actual_file_size);
is_pkg_name = 0;
actual_file_size = 0;
printf("The string is:%s\n", pkg_name);
}
Terminal output:

Well thank you to kaylum and this article: How to get char* with unknown length in C?
I was able to solve my issue by removing the function and using realloc inside the while loop please see below and I hope it helps someone else out in the future!
The pkg_name & pkg_install_dir are still using a char buffer because I realized using the realloc way from the article the two points of memory were rolling over each other (good amount of time to figure that out and I will never get back!).
Learning C is fun!
int read_db()
{
FILE *db;
db = fopen("/tmp/devpkg/db/db", "r");
char *pkg_name = malloc(MAX_CHAR_BUFF);
char *pkg_install_dir = malloc(MAX_CHAR_BUFF);
int is_pkg_name = 1;
int actual_file_size = 0;
while(1)
{
char c = fgetc(db);
if(c == EOF)
{
pkg_install_dir = realloc(pkg_install_dir, (actual_file_size - 1));
pkg_install_dir[actual_file_size - 1] = '\0';
break; // while loop will finish here
}
if(is_pkg_name) {
pkg_name[actual_file_size] = c;
} else {
pkg_install_dir[actual_file_size] = c;
}
actual_file_size++;
if(c == ',')
{
pkg_name = realloc(pkg_name, (actual_file_size - 1));
pkg_name[actual_file_size - 1] = '\0';
is_pkg_name = 0;
actual_file_size = 0;
printf("The string is:%s\n", pkg_name);
}
}
fclose(db);
free(pkg_name);
free(pkg_install_dir);
return 0;
}

Related

Code no longer providing any output in terminal

I have been working on a hangman game for my class which is due today and just now it decided to no longer provide any output from my code. If someone could please give it a look so I can go back to possibly submitting this assignment, I would be very appreciative. I dont know what changed specifically.
char **readWordList(char *, int *);
int main(int argc, char *argv[]) {
char **wordList;
char inputFile[100];
int count = 0;
int i;
if (argc != 2) {
printf("You need to provide the word list file name.\n ");
printf("Usage: $0 filename\n");
return -1;
}
wordList = readWordList(argv[1], &count); //function (target input[s], y placeholder var)
if (wordList == NULL) {
printf("Read word failed\n");
exit(1);
}
printf("fortnite");
int a = 0; //placeholder variables
int b = 0;
int c = 0;
int v = 0;
int g = 0;
int hit = 0;
srand(time(NULL)); //random variable for word selection
int r = rand() % 3;
int chances = 10;
char *word = wordList[r]; //address word from line.txt
char guess;
char misses[10];
int lettercount = 0;
//make blank variable by reading random accessed word
for (size_t a = 0; word[a] != 0; a++) {
lettercount++;
}
char space[lettercount];
// write underscores in place of spaces in temporary array
for (size_t c = 0; word[c] != '\0'; c++) {
space[c] = 95;
}
char blank[lettercount * 2]; //equal to array size empty array
// borrowing my spacename function, but seems to make artifacts in blank input now
int t = 0;
int k = 0;
while (space[t] != '\0') {
k = 2 * t;
if (k > lettercount * 2 - 2) {
blank[k] = space[t];
break;
}
blank[k] = space[t];
blank[k + 1] = ' ';
}
while (chances > 0) {
printf("Chances:%d\n", chances);
printf("Misses:%d\n", misses);
printf("Word:%s\n", blank);
printf("Guess[Q]:");
scanf("%c\n", &guess);
while (word[b] != '\0') {
if (guess = 'Q') {
exit(0);
}
if (guess = word[b]) {
v = b * 2;
blank[v] = guess;
b++;
hit = 1;
}
b++;
}
if (hit != 1) {
misses[g] = guess;
}
if (hit = 1) {
hit = 0;
}
chances--;
g++;
}
}
There are multiple problems in the code, including some serious ones:
the #include lines are missing.
the readWordList function is missing.
if (guess = 'Q') sets guess to 'Q' and evaluates to true. You should write if (guess == 'Q')
if (guess = word[b])... same problem.
printf("Misses:%d\n", misses); should be printf("Misses:%s\n", misses); and misses should be initialized as the empty string.
printf("Word:%s\n", blank); has undefined behavior as blank is not null terminated.
while (space[t] != '\0') may iterate too far as space does not have a null terminator since it's length is lettercount and all elements have been set to 95 ('_' in ASCII). Yet since you never increment t, you actually have an infinite loop. Use a simple for loop instead: for (t = 0; i < lettercount; t++)
scanf("%c\n", &guess); reads a character and consumes any subsequent white space, so the user will have to type another non space character and a newline for scanf() to return. You should instead use scanf(" %c", &guess);
while (word[b] != '\0') will iterate beyond the end of the array after the first guess because you do not reset b to 0 before this loop. Furthermore, b is incremented twice in case of a hit. You should use for loops to avoid such silly mistakes.
if (hit = 1) { hit = 0; }... the test is incorrect (it should use ==) and you could just write hit = 0; or better set hit to 0 before the inner loop.
inputFile is unused.
You should compile with gcc -Wall -Wextra -Werror to avoid such silly bugs that can waste precious time.
i fixed it, i lost a variable which provided the chance that a while loop would end for the spacing array function
sorry for being annoying

Why do the values in my dynamically-allocated memory look like they're being overwritten

I'm working on an assignment that is supposed to parse a string into separate tokens without the use of the c string library and while dynamically allocating any necessary memory. I thought I had everything working correctly, except now it looks like every value is being overwritten every time I write a new value.
Here's my code. Sorry it's a mess, I've been in a hurry and reluctantly have been working with functions I don't fully understand. The problem is probably something dumb, but I'm out of time and it's clear I probably wont be able to figure it out myself.
int makearg(char s[], char **args[]);
int main() { char **tokenArray; char strInput[MAXSTRING]; int tokenResult; int i = 0;
printf("Input String to be Parsed: "); scanf("%[^\n]%*c", strInput);
tokenResult = makearg(strInput, &tokenArray);
printf("argc: %d\n", tokenResult); for (i = 0; i < tokenResult; i++) {
printf("arg(%d): %s\n", i, tokenArray[i]); } }
int makearg(char s[], char **args[]) { int numTokens = 0; int lastSpace = 0; int i; int fakeI; char token[MAXSTRING]; int subFromPos = 0; int firstToken = 1;
*args = NULL; while ((s[i] != '\n') && (s[i] != '\0') && (s[i] != '\r')) {
fakeI = i;
if ((s[i + 1] == '\n') || (s[i + 1] == '\0'))
{
fakeI = i + 1;
}
token[i - lastSpace - subFromPos] = s[i];
if ((s[fakeI] == ' ') || (s[fakeI] == '\n') || (s[fakeI] == '\0') || (s[fakeI] == '\r'))
{
if (firstToken == 1)
{
token[fakeI - lastSpace] = '\0';
firstToken = 0;
} else if (firstToken == 0){
token[i - lastSpace] = '\0';
printf("Saved Token 1: %s\n", *args[numTokens - 1]); //test to see if the token got written properly
if (numTokens > 1){
printf("Prior Saved Token: %s\n", *args[numTokens - 2]); //test to see if the tokens are overwritten
}
if (numTokens > 2){
printf("Prior Saved Token 2: %s\n", *args[numTokens - 3]); //test to see if the tokens are overwritten
}
}
*args = realloc(*args, (numTokens + 1));
args[numTokens] = NULL;
args[numTokens] = realloc(args[numTokens], (fakeI - lastSpace + 1));
*args[numTokens] = token;
printf("Saved Token: %s\n", *args[numTokens]); //test to see if the token got written properly
numTokens++;
lastSpace = fakeI;
subFromPos = 1;
}
i++; } numTokens++; return numTokens; }
For whatever reason Saved Token, Saved Token 1, Prior Saved Token, and Prior Saved Token 2 all print the same value every time they run (by which I mean if one of them prints the word "hello", they all print the word hello. That seems to tell me that the previous data is being overwritten.
Additionally, the for-loop in the main function is supposed to go through and print every value in the array, but instead it's only printing the following (in this scenario I was testing with the string "hello my one true friend":
arg(0): friend
arg(1): (null)
arg(2): (null)
What am I doing wrong here? I'm sure it's something dumb that I'm overlooking, but I just can't find it. Am I writing in the data incorrectly? Is it actually not being overwritten and just being printed incorrectly. At this point any advice at all would be greatly appreciated.
Ok well my dev env picked up immediatly
int i; <<<<=====
int fakeI;
char token[255];
int subFromPos = 0;
int firstToken = 1;
*args = NULL;
while ((s[i] != '\n') && (s[i] != '\0') && (s[i] != '\r')) { <<<<<=
gave
C4700 uninitialized local variable 'i' used
after that all bets are off

Printing to stderr using fprintf in C

I am writing a C program that takes in a text file describing a game of Solitaire. The program will then take in a set of moves, described by the user in the text file, and go through the moves, modifying the state of the game.
Currently, I am processing the moves, if there is an invalid move, I stop a while loop, and print to standard error the move in the format "Move M is illegal: (move)".
char* errString = malloc(sizeof(char) * 10);
errString[9] = '\0';
printString(errString);
int processedMove = 0;
int somethingWrong = 1;
while (processedMove < movesStack.size) {
somethingWrong = processMove(movesStack.cards[processedMove].rank, movesStack.cards[processedMove].suit, &clubsFoundationStack, &diamondsFoundationStack, &heartsFoundationStack, &spadesFoundationStack, &colSevenDown, &colSixDown, &colFiveDown, &colThreeDown, &colFourDown, &colTwoDown, &colOneDown, &colSevenUp, &colSixUp, &colFiveUp, &colThreeUp, &colFourUp, &colTwoUp, &colOneUp, &stockDown, &stockUp, &limitValue, &turnValue);
if (somethingWrong != 1) {
printMove(movesStack.cards[processedMove].rank, movesStack.cards[processedMove].suit, &errString);
printString(errString);
processedMove++;
printf("%d %s\n",processedMove, errString);
fprintf(stderr, "Move %d is invalid %s\n", processed Move, errString);
break;
}
processedMove++;
}
The above is in my main method. printString will be given below, it simply prints the given string.
processMove, takes the stacks of cards and process a move, it will return -1 if the move is invalid, and -2 if the move has a formatting error.
printMove, takes a rank, and suit, and a string, and writes the error to the given string, this would be printed in the fprintf statement.
After running the above code, I am left with this output, you can see the first call of printString(errString), followed by the second call, after errString has been modified by printMove function. Then finally you see the printf statement, which prints the value of processedMove and errString.
Commencing the printing of the string with indices
c[0]: h
c[1]: o
c[2]:
Commencing the printing of the string on one line
ho
Commencing the printing of the string with indices
c[0]: 5
c[1]: -
c[2]: >
c[3]: 2
Commencing the printing of the string on one line
5->2
6 5->2
the function printString
void printString(char* c) {
if (c == NULL) {
printf("string is null\n");
return;
}
printf("\nCommencing the printing of the string with indices\n");
for (int i = 0; i < strlen(c); i++) {
if (c[i] == '\n') {
printf(" c[%d]: newline\n", i);
continue;
}
printf(" c[%d]: %c\n", i, c[i]);
}
printf("Commencing the printing of the string on one line \n");
printf(" ");
for (int i = 0; i < strlen(c); i++) {
if (c[i] == '\n' || c[i] == ' ') {
continue;
}
printf("%c", c[i]);
}
printf("\n");
}
and the function printMove
void printMove(char f, char s, char** errString) {
char* ret = malloc(sizeof(char) * strlen(*errString));
if (f == '.' && s == '.') {
ret[0] = '.';
ret[1] = '\0';
}
else if (f == 'r' && s == 'r') {
ret[0] = 'r';
ret[1] = '\0';
}
else {
ret[0] = f;
ret[1] = '-';
ret[2] = '>';
ret[3] = s;
ret[4] = '\0';
}
*errString = ret;
}
Thank you for your time, and any solution is welcome.
So the problem here is, that it you cannot use your own variables in a stream to stderr.

Dont get the output out of char palindrom[]

i trying to make a palindrom out of the user input.
Im saving the user input as array in char eingabe[]
with int i im counting the index of the used arrays.
Then i want to copy the reversed value of eingabe in palindrom and then printf both of them to get the palindrom.
My i and j are counting correctly, but i dont get the output for palindrom.
I hope you can help me.
#include <stdio.h>
int main(){
char eingabe[20];
char palindrom[20];
int i = 0;
int j = 0;
char c;
do{
c = getchar();
if (c != EOF){
eingabe[i] = c;
i++;
}
} while (c != EOF);
eingabe[i] = '\0';
do{
palindrom[j] = eingabe[i];
j++;
--i;
} while (i != 0);
palindrom[j] = '\0';
printf("\n\n%s",eingabe);
printf("%s\n\n",palindrom);
return 0;
}
It is sometimes very helpful to add printf's to see what is going on. For example, if I add:
do {
printf("palindrom[%d] = eingabe[%d]\n", j, i);
palindrom[j] = eingabe[i];
then the output is:
abcde
palindrom[0] = eingabe[5]
palindrom[1] = eingabe[4]
palindrom[2] = eingabe[3]
palindrom[3] = eingabe[2]
palindrom[4] = eingabe[1]
eingabe: "abcde"
palindrom: ""
The problem is immediately obvious: the array index is off by 1. Since the first character of palindrom ([0]) gets set to the last character of eingabe ([5]) which is "\0", then C sees it as an empty string.
This is easily corrected by moving the --i to the top of the loop:
do {
--i;
palindrom[j] = eingabe[i];
j++;
} while (i != 0);
Try palindrom[j] = eingabe[i-1]; Instead.
even this will work:
i=0;
do{
palindrom[j++] = eingabe[i++];
} while ( eingabe[i]!='/0');
j=0;
do{
palindrom[j++] = eingabe[i--];
} while ([i]>0);
palindrom[j] = '\0';

Replacing a substring in a string - c

I'm trying to do a program which finds a substring in a string and replaces it with another substring entered by user. My code doesn't give a compile or run-time error, but it just doesn't work. I put printfs in the while loop which I wrote a comment line near it, and the program doesn't go into first if -I put another comment line near it. It prints a, h and i. The other parts in loop aren't working. Here's my code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char *findAndReplace(char *sentence, char *word1, char *word2);
void main()
{
char sentence[1000];
char word1[200];
char word2[200];
int length;
printf("Please enter a sentence: ");
gets(sentence);
printf("Please write the word to be replaced: ");
gets(word1);
printf("Please write the word to be put instead: ");
gets(word2);
findAndReplace(sentence, word1, word2);
system("pause");
}
char* findAndReplace(char *sentence, char *word1, char *word2)
{
char *search, *tempString[1000];
int a, b, c, d, i = 0, j, sentenceLength, word1Length, searchLength;
sentenceLength = strlen(sentence);
printf("Length of %s is %d\n", sentence, sentenceLength);
printf("Finding ");
puts(word1);
search = strstr(sentence, word1);
searchLength = strlen(search);
word1Length = strlen(word1);
strcpy(tempString, sentence);
if(search != NULL)
{
printf("Starting point: %d\n", sentenceLength - searchLength);
}
else
{
printf("Eşleşme bulunamadı.\n");
}
j = 0;
while(j < sentenceLength + 1) //This loop
{
printf("a");
if(word1[i] == tempString[j])
{
printf("b");
if(i == word1Length)
{
c = j;
printf("c");
for(d = 0; d < word1Length; d++)
{
tempString[c - word1Length + d + 1] = word2[d];
printf("d");
}
i = 0;
j++;
printf("e");
}
else
{ printf("f");
i++;
j++;
}
printf("g");
}
else{
printf("h");
i = 0;
j++;
}
printf("i");
}
puts(tempString);
}
You've made a decent start, but you're making this a lot harder than it needs to be. One way to minimize errors is to rely on standard library functions when there are any that do the work you need done. For example:
char tempString[1000];
char *search;
search = strstr(sentence, word1);
if (search) {
ptrdiff_t head_length = search - sentence;
int sentence_length = strlen(sentence);
int word1_length = strlen(word1);
int word2_length = strlen(word2);
if (sentence_length + word2_length - word1_length < 1000) {
/* construct the modified string */
strncpy(tempString, sentence, head_length);
strcpy(tempString + head_length, word2);
strcpy(tempString + head_length + word2_length, search + word1_length);
/* copy it over the original (hope it doesn't overflow!) */
strcpy(sentence, tempString);
} else {
/* oops! insufficient temp space */
}
} /* else the target word was not found */
That covers only the search / replacement bit, fixing the error in tempString's type first pointed out by iharob. Also, it replaces only the first occurrence of the target word, as the original code appeared to be trying to do.
Among other things you have declared tempString as char* tempString[1000] which is an array of uninitialized character pointers so when you do
strcpy(tempString, sentence);
you are basically getting undefined behavior.
Use also fgets instead of gets when you input strings - even though you have rather large buffers it can happen one day that you pipe in a text file and get a stack overflow.
If I were you I would use strtok and split your sentence in words, then check each word. If word is same replace otherwise add sentence word to a new string.
e.g.
char newString[1000] = {0};
for (char* word = strtok(sentence, " "); word != NULL; word = strok(NULL, " "))
{
if (!strcmp(word, word1)) // here you may wanna use strncmp or some other variant
{
strcat(newString, word2);
}
else
{
strcat(newString, word);
}
strcat(newString, " ");
}
newString[strlen(newString)-1] = '\0';

Resources