Printing to stderr using fprintf in C - 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.

Related

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

Strcat adding "blank space" to array

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;
}

How can I copy strings to another array separated with '\n' character while I get those strings?

I want to get from user multiple line strings.
How I can do that?
User doesn’t know beforehand how many “paragraphs” wants.
User Input (example_1):
Hello! (clicks Enter button)
World! (clicks Enter button)
(clicks Enter button)
Output:
Hello!
World!
User Input (example_2):
(clicks Enter button)
Output:
(nothing)
There are some notes here:
1. You could have used getline() function instead of scanning characters one by one.
2. Assuming that for now we want to use scanf, you might not now the paragraph's length beforehand, so its better to use a linked list of lines in which you allocate memory dynamically. Here is a working example:
#include <stdio.h>
#include <stdlib.h>
typedef struct _line{
char * chars_in_line;
struct _line * next_line;
}line;
void fill_paragraph_lines(line * first_line , int max_size){
first_line->chars_in_line = (char *)malloc(max_size * sizeof(char));
first_line->next_line = NULL;
line * current_line = first_line;
int i;
char aux = '\0';
while(1){
for(i = 0 ; i < max_size ; i++){
if(aux == '\0'){
printf("enter a character: ");
scanf(" %c" , &aux);
}
// if the received character is not '\n' put that in line
if(aux != '\n'){
current_line->chars_in_line[i] = aux;
aux = '\0';
}
// if you receive \n as an input character, set the ending \0 and break from for loop
else{
current_line->chars_in_line[i] = '\0';
aux = '\0';
break;
}
// reset aux character to its initial value
aux = '\0';
// if you reach max_size also end the string with '\0', no matter what character you received from user
if(i == max_size - 1){
current_line->chars_in_line[i] = '\0';
printf("\nmax line characters reached\n");
aux = '\0';
}
}
// the user can end a paragraph by inputting \n, when previous line is completed
char possible_paragraph_ending;
printf("enter a character: ");
scanf(" %c" , &aux);
if(aux == '\n')
return;
// if the user inputs another character, start a new line
line * new_line = (line*)malloc(sizeof(line));
new_line -> chars_in_line = (char *)malloc(max_size * sizeof(char));
new_line ->next_line = NULL ;
// chain the new line to the previous lines and move the pointer current line to the
// newly created line
current_line->next_line = new_line;
current_line = new_line;
}
}
void destroy_paragraph(line * first_line){
if(first_line == NULL)
return ;
line * traverse_line = (line *)first_line->next_line;
line * dealloc_line = first_line;
while(1){
free(dealloc_line->chars_in_line);
free(dealloc_line);
if(traverse_line == NULL)
return;
dealloc_line = traverse_line;
traverse_line = dealloc_line->next_line;
}
}
void print_paragraph(line * first_line){
line * traverse_line = first_line;
while(traverse_line != NULL){
printf("%s\n" , traverse_line->chars_in_line);
traverse_line = traverse_line->next_line;
}
}
int main() {
line * first_line = (line *)malloc(sizeof(line));
fill_paragraph_lines(first_line , 10) ;
print_paragraph(first_line);
destroy_paragraph(first_line);
return 0 ;
}
In the code above, you need to hit enter after each character in a line. If you want to end a line, you have to press Return 2 times consecutively and you need to press Return 3 times to end a paragraph.
When a new line needs to be generated, memory is dynamically allocated. destroy_paragraph() needs to be called to free memory.
This code does what you are expected to do. I simplified the signature of the function get_string (not sure if the signature you provided was required or not). To the function we pass the array paragraphs (for proof of concept I am using an array with 300 positions, however if you should use malloc and realloc to adjust the size as needed) and the number of strings read in the function.
NOTE: Updated code to count words per paragraph in array as requested by OP.
#include <stdio.h>
#include <string.h>
void get_string(char *paragraphs, int *n) {
char aux[30], i = 0, parg_cur_length = 0;
do{
fgets(aux, sizeof(aux), stdin);
if(aux[0] == '\n')
break;
for(i=0; i< strlen(aux); i++){
paragraphs[parg_cur_length + i] = aux[i];
}
parg_cur_length += strlen(aux);
paragraphs[parg_cur_length] = '\0';
parg_cur_length++;
(*n)++;
}while(aux[0] != '\n');
}
int main()
{
char paragraphs[300];
char * iter_paragraphs = paragraphs;
int n_times = 0, n_chars = 0;
get_string(paragraphs, &n_times);
// let's print what we have
for(int i = 0; i< n_times; i++) {
n_chars = printf("%s", iter_paragraphs);
iter_paragraphs += n_chars+1;
}
// reset pointer
iter_paragraphs = &paragraphs[0];
// let's counts the words per paragraph
int j = 0, word_cnt = 0;
for(int i = 0; i< n_times; i++) {
while(*(iter_paragraphs + j) != '\0') {
if( *(iter_paragraphs + j) == ' ')
word_cnt++;
j++;
}
// assuming last word does not have space but \n instead
n_chars = printf("paragraph %d has %d words\n", i+1, word_cnt+1);
word_cnt = 0;
// move to next pos in array due to \0
j++;
}
}
Nevertheless, IMO a cleaner approach for this would be to use a matrix (char **) as user3121023 suggested.

Find palindromes in sentence

I am trying to write a piece of C code that takes a sentence and returns all the palindromes in that sentence, each in a new line. For example, the sentence "I like to race a civic racecar" would return:
civic
racecar
I've tried to use some debugging software (lldb, as I'm a mac user), but found it a bit confusing. The code below is what I have written. It's returning a segmentation fault, and I'm having trouble identifying it within my program.
int is_palin(char c[], int length)
{
int front = 0;
int back = length - 1; /* account for length starting at 0 */
if (length % 2 == 0){ /* check for even palindromes */
int middle = (length /2) -1 ;
while (front< middle + 1){
if (c[front] != c[back]){
return 0;}
front = front + 1;
back = back -1;
}
}
else { /* check for odd palindromes */
int middle = ((back - 2) / 2 ) + 1;
while (front != middle){
if (c[front] != c[back]){
return 0;}
front = front + 1;
back = back -1;}
}
return 1;
}
int is_delimiting_char(char ch)
{
if(ch == ' ') //White space
return 1;
else if(ch == ',') //Comma
return 1;
else if(ch == '.') //Period
return 1;
else if(ch == '!') //Exclamation
return 1;
else if(ch == '?') //Question mark
return 1;
else if(ch == '_') //Underscore
return 1;
else if(ch == '-') //Hyphen
return 1;
else if(ch == '(') //Opening parentheses
return 1;
else if(ch == ')') //Closing parentheses
return 1;
else if(ch == '\n') //Newline (the input ends with it)
return 1;
else
return 0;
}
/////////////////////////////////////////////
//---------------------------------------------------------------------------
// MAIN function
//---------------------------------------------------------------------------
int main (int argc, char** argv) {
char input_sentence[100];
int i=0;
char current_char;
int delimiting_char;
char word[20];
int word_length;
int have_palindrome = 0;
/////////////////////////////////////////////
/////////////////////////////////////////////
/* Infinite loop
* Asks for input sentence and prints the palindromes in it
* Terminated by user (e.g. CTRL+C)
*/
while(1) {
i=0;
print_char('\n');
print_string("input: ");
/* Read the input sentence.
* It is just a sequence of character terminated by a new line (\n) character.
*/
do {
current_char=read_char();
input_sentence[i]=current_char;
i++;
} while (current_char != '\n');
/////////////////////////////////////////////
print_string("output:\n");
int char_index = 0;
for(int k=0; k<i; k++) {
palin = 1;
current_char = input_sentence[k];
delimiting_char = is_delimiting_char(current_char);
if(delimiting_char) {
if (char_index > 0) { //Avoids printing a blank line in case of consecutive delimiting characters.
word[char_index++] = '\n'; //Puts an newline character so the next word in printed in a new line.
word_length = word_length + 1;
if (is_palin(word, word_length) && word_length > 1){
have_palindrome = 1;
for(int j=0; j<char_index; j++) {
print_char(word[j]);
}
word_length = 0;
char_index = 0;
}
} }
else {
word[char_index++] = current_char;
word_length = word_length + 1;
}
}
if (have_palindrome == 0){
print_string("Sorry! No palindromes found!"); }
}
return 0;
}
Also wondering if anyone has good videos or sites for learnign how to use lldb, when one has never used anything of the sort before. Thanks!
There are several things wrong here:
word_length is uninitialised at first use, so statements like word_length = word_length + 1 lead to undefined behaviour. In fact, you have two different variables, char_index and word_length, that should always have the same value. Instead of going through the hassle to keep them in sync, use just one variable.
You reset both char_index and word_length to zero only if a palindrome was found. You should reset if after every word, of course.
The line palin = 1; is probably a leftover from older code. You should also reset have_palindrome after each line. In general, you should take more care when defining variables.
By adding a newline to your word you make printing a bit easier, but you will never find a palindrome, because the newline at the end is taken into account when checking for the palindrome.
Your code for reading with read_char, which is probably an alias to getchar, needs to check for the end of input.
You don't need to distinguish between even and odd sized palindromes. Just make the condition that front < back and be done with it. The middle character of an odd sized palindrome doesn't matter. (That's not an error, your code is just needlessly complicated.)

Convert String of characters to Float dynamically

I've been having some problems with this code below...
The main idea of the code is to read line by line and convert chars strings into floats and save the floats in a array called nfloat.
The input is a .txt containing this: n = the number of strings, in this case n = 3
3
[9.3,1.2,87.9]
[1.0,1.0]
[0.0,0.0,1.0]
The first number, 3 is the number of vectors as we can see in the image, but that number isn't static, the input can be 5 or 7, etc instead of 3.
So far, I've started doing the following, (for only 1 vector case) but the code has some memory errors I think:
int main(){
int n; //number of string, comes in the input
scanf("%d\n", &n);
char *line = NULL;
size_t len = 0;
ssize_t read;
read = getline(&line,&len,stdin); //here the program assigns memory for the 1st string
int numsvector = NumsVector(line, read);//calculate the amount of numbers in the strng
float nfloat[numsvector];
int i;
for (i = 0; i < numsvector; ++i)
{
if(numsvector == 1){
sscanf(line, "[%f]", &nfloat[i]);
}
else if(numsvector == 2){
if(i == 0) {
sscanf(line, "[%f,", &nfloat[i]);
printf("%f ", nfloat[i]);
}
else if(i == (numsvector-1)){
sscanf((line+1), "%f]", &nfloat[i]);
printf("%f\n", nfloat[i]);
}
}
else { //Here is where I think the problems are
if(i == 0) {
sscanf(line, "[%f,", &nfloat[i]);
printf("%f\n", nfloat[i]);
}
else if(i == (numsvector-1)) {
sscanf((line+1+(4*i)), "%f]", &nfloat[i]);
printf("%f\n", nfloat[i]);
}
else {
sscanf((line+1+(4*i)), "%f,", &nfloat[i]);
printf("%f\n", nfloat[i]);
}
}
}
Well, the problems come with the sscanf instructions I think, in the case of a string with two floats or one, the code works fine but in the case of 3 or more floats, the code doesn't work well and I can't understand why...
Here I attach the function too, but It seems to be correct... the focus of the problem remains on the main.
int NumsVector(char *linea, ssize_t size){
int numsvector = 1; //minimum value = 1
int n;
for(n = 2; n<= size; n++){
if (linea[n] != '[' && linea[n] != ']'){
if(linea[n] == 44){
numsvector = numsvector + 1;
}
}
}
return numsvector;
}
Please could someone help me understand where is the problem?
Ok - if you replace your current for loop with this, your nfloat array should end up with the right numbers in it.
/* Replaces the end ] with a , */
line[strlen(line) - 1] = ',';
/* creates a new pointer, pointing after the first [ in the original string */
char *p = line + 1;
do
{
/* grabs up to the next comma as a float */
sscanf(p, "%f,", &nfloat[i]);
/* prints the float it's just grabbed to 2 dp */
printf("%.2f\n",nfloat[i]);
/* moves pointer forward to next comma */
while (*(p++) != ',');
}
while (++i < numsvector); /* stops when you've got the expected number */

Resources