Printing C Array to a terminal - c

I need to read in a file from C, store it in an array and print its contents. For some reason I keep seeing octal in my output near the end. I am dynamically creating the array after counting how many lines and characters are in it after opening the file.
output:
Abies
abies
abietate
abietene
abietic
abietin
\320ѿ_\377Abietineae --> umlaut? where did he come from?
y\300_\377abietineous
code:
int main(int argc, char ** argv) {
char c = '\0';
FILE * file;
int i = 0, j = 0, max_line = 0, max_char_per_line = 0;
/* get array limits */
file = fopen(argv[1], "r");
while ((c = fgetc(file)) != EOF){
if (c == '\n'){
max_line++; j++;
if (j > max_char_per_line){
max_char_per_line = j;
}
j = 0;
continue;
}
j++;
}
rewind(file);
/* declare array dynamically based on max line and max char */
char word[max_line][max_char_per_line];
/*read in file*/
j = 0; c = '\0';
while ((c = fgetc(file)) != EOF){
if (c == '\n'){
word[i][j] = '\0';
i++; j=0;
continue;
}
word[i][j] = c;
j++;
}
word[i][j] = '\0';
fclose(file);
for (i = 0; i < max_line; i++){
printf("%s\n", word[i]);
}
return 0;
}

Change read routine:
if (c == '\n'){
word[i][j] = 0x0;
i++; j=0;
continue;
}
and add the "\n" back in the printf routine.
for (i = 0; i < max_line; i++){
printf("%s\n", word[i]);
}
C strings are zero-terminated, not "\n"-terminated, so when you printf()ed them, printf() did not know where to stop printing.

You aren't terminating your strings. You need to add the null-terminator: \0, after the last character for each line.
In your first loop, you determine enough space for the longest line, including a newline character.
If you want to keep the newlines in your input array, just add 1 to max_char_per_line, and add the null-terminator after the newline character when you finish each line in your second loop.
If you don't need the newline in your input array, instead simply use that space for the null-terminator.

Not that it explains exactly the phenomenon you observe, but it may. You do not seem to take into account the terminating zero byte when calculating array boundaries. Just ++ the max_char_per_line after doing the calculations. And don't forget to add this zero byte if the array isn't guaranteed to be zero-initialized.
edit: do you see these lines after the output or in one these lines of output?

Related

fgets() and scanf() not working properly in unison. Buffer problem encountered

My assignment: -
Write a program that replaces the occurence of a given character (say
c) in a primary string (say PS) with another string (say s).
Input: The first line contains the primary string (PS) The next line
contains a character (c) The next line contains a string (s)
Output: Print the string PS with every occurence of c replaced by s.
Test case 1: -
Input: -
abcxy
b
mf
Expected output: -
amfcxy
Test case 2: -
Input: -
Al#bal#20owL
l
LL
Expected output: -
ALL#baLL#20owL
My code below: -
#include <stdio.h>
#include <stdlib.h>
int main() {
char PS[101];
char c;
char S[11];
fgets(PS, 101, stdin); //PS value input.
scanf("%c", &c);
if (c == '\n' || c == '\0') {
scanf("%c", &c); //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
}
fgets(S, 11, stdin); //S value input.
int i = 0;
while (PS[i] != '\0') { //Removing the '\n' from PS
if (PS[i] == '\n') {
PS[i] = '\0';
break;
}
i++;
}
i = i - 1; //i now holds the value of the size of the string PS (excluding '\0')
int j = 0;
while (S[j] != '\0') {
if (S[j] == '\n') {
S[j] = '\0';
break;
}
j++;
}
j = j - 1; //j now holds the value of the size of the string S (excluding '\0')
int k = 0; //work as an initializer
int move = 0; //work as an initializer.
while (PS[k] != '\0') { //This loops checks the whole array for the same character mentioned in char 'c'
if (PS[k] == c) {
for (move = i; move > k; move --) { //This loop advances the all the characters in PS by '(j - 1)' steps to make space for string S characters.
PS[move + (j - 1)] = PS[move];
}
for (move = 0; move < j; move++) { //This loop adds all the characters of string S into string PS at the relevant place.
PS[k + move] = S[move];
}
i = i + (j - 1); // 'i' now holds the new value of size of string PS after adding all the characters of string S.
}
k++;
}
puts(PS);
return 0;
}
Now the problem is that the code is not taking the input for string S.
After inputting first 2 inputs, it executes and gives a gibberish answer. I cannot figure out the bug, but what I do know is that there is some issue related to the buffer in C. Please help.
Edit: -
Thanks to #WeatherVane I have now edited the code with this: -
scanf("%c", &c);
if (c == '\n' || c == '\0') {
scanf("%c", &c); //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
}
char x;
x = getchar(); //New addition. It eats the '\n' after scanf().
fgets(S, 11, stdin); //S value input.
Now my code is working fine but the output is still not correct. It is sometimes failing to copy the last char from string S or giving me gibberish output.
The problem with the code was: -
i = i - 1; //i now holds the value of the size of the string PS (excluding '\0')
j = j - 1; //j now holds the value of the size of the string S (excluding '\0')
The value of i and j are the true values of the size of string PS and string S; not i = i - 1 and j = j - 1.
Lesson learnt from this assignment: -
scanf() does not treat '\n' in any way. It WILL be left in the
buffer.
If possible use fgets and then remove '\n' from your respective array/pointer.
Be extra careful of your C buffer when dealing with chars and strings.
The final correct code is: -
#include <stdio.h>
#include <stdlib.h>
int main()
{
char PS[101];
char c;
char S[11];
fgets(PS, 101, stdin); //PS value input.
scanf("%c", &c);
if(c == '\n' || c == '\0')
{
scanf("%c", &c); //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
}
char x;
x = getchar(); //New addition. It eats the '\n' after scanf().
fgets(S, 11, stdin); //S value input.
int i = 0;
while(PS[i] != '\0') //Removing the '\n' from PS
{
if(PS[i] == '\n')
{
PS[i] = '\0';
break;
}
i++;
}
i = i; //i now holds the value of the size of the string PS (excluding '\0')
int j = 0;
while(S[j] != '\0')
{
if(S[j] == '\n')
{
S[j] = '\0';
break;
}
j++;
}
j = j; //j now holds the value of the size of the string S (excluding '\0')
int k = 0; //work as an initializer
int move = 0; //work as an initializer.
while(PS[k] != '\0') //This loops checks the whole array for the same character mentioned in char 'c'
{
if(PS[k] == c)
{
for(move = i; move > k; move --) //This loop advances the all the characters in PS by '(j - 1)' steps to make space for string S characters.
{
PS[move + (j - 1)] = PS[move];
}
for(move = 0; move < j; move++) //This loop adds all the characters of string S into string PS at the relevant place.
{
PS[k + move] = S[move];
}
i = i + (j - 1); // 'i' now holds the new value of size of string PS after adding all the characters of string S.
}
k++;
}
puts(PS);
return 0;
}
Warning: -
The above code is very unoptimised and unreadable. Do not use it for
long term projects. It just "works".
Any suggestions for improvements of the above code are welcomed in
the comments.
Further necessary reading material recommended if you face any issue regarding C buffer in the future: -
Read 1
Read 2

How many characters are in given array but spaces

I am trying to find out how many characters are in the given array except blanks
but it's not working, k supposed to count blanks and substract them from i[characters + blanks] but it doesn't.
int i= 0;
int n= 0;
int k= 0;
char c[256] = {};
fgets(c ,256, stdin);
while(c[i] != '\0' ){
if(c[i] == ' '){
i++;
k++;
continue;}
i++;}
printf("%d",i-k);
Few observation, here
fgets(c ,256, stdin);
fgets() stores \n at the end of buffer if read. From the manual page of fgets()
If a newline is read, it is stored into the buffer.
A terminating null byte ('\0') is stored after the last character in
the buffer
Remove the trailing \n first and then iterate over it. For e.g
fgets(c, sizeof(c), stdin);
c[strcspn(c, "\n")] = 0; /* remove the trailing \n */
Also use of continue is not required here i.e you can achieve the task without using it. For e.g
int main(void) {
int i= 0;
int k= 0;
char c[256] = ""; /* fill whole array with 0 */
fgets(c, sizeof(c), stdin);
c[strcspn(c, "\n")] = 0; /* remove the trailing \n */
while(c[i] != '\0' ){ /* or just c[i] */
if(c[i] == ' ') {
k++; /* when cond is true, increment cout */
}
i++; /* keep it outside i.e spaces or not spaces
this should increment */
}
printf("spaces [%d] without spaces [%d]\n",k,i-k);
return 0;
}

printf does not output char array in C

I have a problem with my C program not outputting the string stored in my buffer[ ] array.
My code is:
#include <stdio.h>
#include <ctype.h>
int main()
{
int textSize = 20;
int index, ch;
int count = 0;
int upperCount = 0;
int lowerCount = 0;
char buffer[textSize];
FILE *pToFile = fopen("input.txt", "r");
if (pToFile != NULL)
{
while (!feof(pToFile))
{
/* Read in a single line from "stdin": */
for(index = 0; (index < textSize) && ((ch = fgetc(pToFile)) != EOF)
&& (ch != '\n'); index++) {
if(islower(ch))
{
buffer[index] = toupper(ch);
count++;
upperCount++;
}
else if(isupper(ch))
{
buffer[index] = tolower(ch);
count++;
lowerCount++;
}
else
{
buffer[index] = (char)ch;
count++;
}
}
}
}
fclose(pToFile);
/* Terminate string with null characters: */
buffer[index] = '\0';
/* Print output out onto screen */
printf("%s\n", buffer);
printf("Read %d characters in total, %d converted to upper-case, %d to lower-case\n",
count, upperCount, lowerCount);
return 0;
}
The first printf statement does not print, however the second one does.
Please could anyone help explain why this is the case?
The problem is your with your loops, especially that while (!feof(pToFile)) loop.
Lets say your text contains a single line line less than 19 characters long, that is terminated by a newline. That last bit, the line ending in a newline is important.
What happens when you read the file is that you encounter the newline, break the inner for loop and you are back in the outer loop. Because we have not passed the end of the file yet feof(pToFile) will return false, and you go back to your for loop.
This time in the for loop the very first time you call fgetc it will notice that you are at the end of the file and return EOF and you break out of the loop. However, because your initializing expression in the for loop is index = 0 you will exit the loop with index being equal to zero.
Now the file is at its end, and feof(pToFile) will return true, and you exit the outer loop, and then you terminate the string in buffer with index being zero, i.e. you do
buffer[0] = '\0';
Now you have an "empty" string that you print.
The simple solution? Skip the outer while loop, you don't need it.

Attach a String to another String in C WITHOUT any spaces

this is my first post in this forum so please be patient.
I need to make a short programm, where the user can enter 2 strings which should be attached afterwards.
I already got this code below (I am not allowed to use other "includes").
What I need to know is: How can I deny any spaces which the user will enter?
Example: 1. String "Hello " | 2. String "World" Result should be "HelloWorld" instead of "Hello World".
#include <stdio.h>
void main()
{
char eingabe1[100];
char eingabe2[100];
int i = 0;
int j = 0;
printf("Gib zwei Wörter ein, die aneinander angehängt werden sollen\n");
printf("1. Zeichenkette: ");
gets(eingabe1);
printf("\n");
printf("2. Zeichenkette: ");
gets(eingabe2);
printf("\n");
while (eingabe1[i] != '\0')
{
i++;
}
while (eingabe2[j] != '\0')
{
eingabe1[i++] = eingabe2[j++];
}
eingabe1[i] = '\0';
printf("Nach Verketten: ");
puts(eingabe1);
}
You have to filter out the spaces as you copy your strings.
You have two string indices, i for the first string and and j for the second string. You could make better use of these indices if you used i for the reading position (of both strings subsequently; you can "reuse" loop counters in independent loops) and j for the writing position.
Here's how. Note that the code attempts to prevent buffer overflow by only adding characters if there is space in the string. This check needs only to be done when copying the second string, because j <= i when you process the first string.
#include <stdio.h>
int main()
{
char str1[100] = "The quick brown fox jumps over ";
char str2[100] = "my big sphinx of quartz";
int i = 0;
int j = 0;
while (str1[i] != '\0') {
if (str1[i] != ' ') str1[j++] = str1[i];
i++;
}
i = 0;
while (str2[i] != '\0') {
if (str2[i] != ' ' && j + 1 < sizeof(str1)) str1[j++] = str2[i];
i++;
}
str1[j] = '\0';
printf("'%s'\n", str1);
return 0;
}
In addition to avoiding spaces between your two words, you also have to avoid the newline ('\n') character placed in the input buffer by the user pressing Enter. You can do that with a simple test after you have read the line with fgets() NOT gets(). gets() is no longer part of the standard C library and should not be used due to insecurity reasons. Plus fgets provides simple length control over the number of characters a user may enter at any time.
Below, you run into trouble when you read eingabe1. After the read, eingabe1 contains a '\n' character at its end. (as it would using any of the line-oriented input functions (e.g. getline(), fgets(), etc) To handle the newline, you can simply compare its length minus '1' after you loop over the string to find the nul character. e.g.:
if (eingabe1[i-1] == '\n') i--; /* remove trailing '\n', update i */
By simply reducing the index 'i', this will guarantee that the concatenation with eingabe2 will not have any spaces or newline characters between the words.
Putting the pieces together, and using fgets in place of the insecure gets, after #define MAX 100'ing a constant to prevent hardcoding your array indexes, you could come up with something similar to:
#include <stdio.h>
#define MAX 100
int main (void)
{
char eingabe1[MAX] = {0};
char eingabe2[MAX] = {0};
int i = 0;
int j = 0;
printf("Gib zwei Wörter ein, die aneinander angehängt werden sollen\n");
printf("1. Zeichenkette: ");
/* do NOT use gets - it is no longer part of the C library */
fgets(eingabe1, MAX, stdin);
putchar ('\n');
printf("2. Zeichenkette: ");
/* do NOT use gets - it is no longer part of the C library */
fgets(eingabe2, MAX, stdin);
putchar ('\n');
while (eingabe1[i]) i++; /* set i (index) to terminating nul */
if (i > 0) {
if (eingabe1[i-1] == '\n') i--; /* remove trailing '\n' */
while (i && eingabe1[i-1] == ' ') /* remove trailing ' ' */
i--;
}
while (eingabe2[j]) { /* concatenate string - no spaces */
eingabe1[i++] = eingabe2[j++];
}
eingabe1[i] = 0; /* nul-terminate eingabe1 */
printf("Nach Verketten: %s\n", eingabe1);
return 0;
}
Output
$ ./bin/strcatsimple
Gib zwei Wörter ein, die aneinander angehängt werden sollen
1. Zeichenkette: Lars
2. Zeichenkette: Kenitsche
Nach Verketten: LarsKenitsche
Let me know if you have any further questions. I have highlighted the changes with comments above.
/**
return: the new len of the string;
*/
int removeChar(char* string, char c) {
int i, j;
int len = strlen(string)+1; // +1 to include '\0'
for(i = 0, j = 0 ; i < len ; i++){
if( string[i] == c )
continue; // avoid incrementing j and copying c
string[ j ] = string[ i ]; // shift characters
j++;
}
return j-1; // do not count '\0';
}
int main(){
char str1[] = "sky is flat ";
char str2[100] = "earth is small ";
strcat( str2, str1 );
printf("with spaces:\n\t'%s'\n", str2) ;
removeChar(str2, ' ');
printf("without spaces:\n\t'%s'\n", str2 );
}
/**
BONUS: this will remove many characters at once, eg "\n \r\t"
return: the new len of the string;
*/
int removeChars(char* string, char *chars) {
int i, j;
int len = strlen(string);
for(i = 0, j = 0 ; i < len ; i++){
if( strchr(chars,string[i]) )
continue; // avoid incrementing j and copying c
string[ j ] = string[ i ]; // shift characters
j++;
}
string[ j ]=0;
return j;
}
Thank you everyone for all the answers.
I got the solution now.
I read some advices from you and will try to remember for the future.
See the code below:
(Excuse me for the strange names for the variables, I use german words)
A few notices:
I am not allowed to use library functions
I am not allowed to use fgets for some reasons as a trainee
#include <stdio.h>
void main()
{
char eingabe1[100];
char eingabe2[100];
int i = 0;
int j = 0;
printf("gib zwei wörter ein, die aneinander angehängt werden sollen\n");
printf("1. zeichenkette: ");
gets(eingabe1);
printf("\n");
printf("2. zeichenkette: ");
gets(eingabe2);
printf("\n");
//Attach Strings
while (eingabe1[i] != '\0')
{
i++;
}
while (eingabe2[j] != '\0')
{
eingabe1[i++] = eingabe2[j++];
}
//Remove Space
eingabe1[i] = '\0';
i = 0;
j = 0;
while (eingabe1[i] != '\0')
{
if (eingabe1[i] != 32)
{
eingabe2[j++] = eingabe1[i];
}
i++;
}
eingabe2[j] = '\0';
printf("Nach verketten: ");
puts(eingabe2);
}
Sounds like homework to me.
I just wanted to mention that you probably shouldn't use sizeof() on strings these days because there may be multibyte characters in there. Use strlen() instead. The only time sizeof() would be appropriate is if you're going to malloc() a certain number of bytes to store it.
I write little loops fairly often to do low level text stuff one character at a time, just be aware that strings in C usually have a 0 byte at the end. You have to expect to encounter one and be sure you put one on the output. Space is 0x20 or decimal 32 or ' ', it's just another character.

C filling an array from a text file

I'm trying to fill an array from a text file. I'm using fgetc and my problem is dealing with the newline characters that are in the text file. I've currently got,
for(i = 0; i < rows; i++){
for(j = 0; j < columns; j++){
if((fgetc(fp) == '\n') || (fgetc(fp) == '\r')){
fgetc(fp);
array[i][j] = fgetc(fp);
else{
array[i][j] = fgetc(fp);
}
printf("i %d j %d char %c code %d\n", i, j, array[i][j], array[i][j]);
}
}
The idea is that if there's a newline character I want to advance the file pointer while in the same i,j position of the loop so I can get the next character. The output for this is jumbled for the first two rows and then it starts reading characters with character code -1. Am I doing something terribly wrong?
Each call to fgetc will advance the file pointer. Try calling it once:
int c = fgetc(fp);
then test the value of c. Store it if you want or go through the loop again.
In your first if() statement, there's a bit of an issue. When you do this:
if((fgetc(fp) == '\n') || (fgetc(fp) == '\r')){
fgetc(fp);
array[i][j] = fgetc(fp);
You actually are calling fgetc(fp) four times. Twice in the if() statement, twice later on.
Perhaps you are looking more for something like this:
for(i = 0; i < rows; i++){
for(j = 0; j < columns; j++){
int test = fgetc(fp);
if(test != '\n' && test != '\r')
array[i][j] = test;
//We want to "undo" the last j++ if we got a whitespace
else
j--;
printf("i %d j %d char %c code %d\n", i, j, array[i][j], array[i][j]);
}
}
In this example, you call fgetc(fp) exactly once per iteration, and if it's not a \n or \r, you put it in your array.
I'm sorry, I have little experience with fgetc(). If you notice something incredibly awful with what I've done, please notify me!
I can immediately see one source of error. In the following line:
if((fgetc(fp) == '\n') || (fgetc(fp) == '\r'))
There are 2 calls to fgetc(). This means that if the first call does not return '\n', another call will be made whose return value is then compared to '\r'. This has the effect of advancing the file pointer twice, as the pointer is advanced each time you call fgetc . A better way to do this would be to fetch one character and then test whether it is '\n' or '\r', and only then incrementing the file pointer with another call to fgetc if this is true. For example:
char letter = fgetc(fp);
if((letter == '\n') || (letter == '\r')
...
...
Try this and see if you still get the same error.
I believe you are getting the character in your evaluation statement twice. Also, typically the CRLF (carriage return and line feed) end of line characters can be two characters. Read http://en.wikipedia.org/wiki/Newline for details on this.
#include <stdio.h>
int main ()
{
FILE *fp;
int c;
fp = fopen("file.txt","r");
if(fp == NULL)
{
fprintf(stderr,"Error opening file");
return(-1);
}
do
{
c = fgetc(fp);
if ((c == '\n') || (c == '\r')) {
fgetc(fp); // skip CR or LF and advance a character
} else {
printf("%c", c); // print all other characters
}
}while(c != EOF);
fclose(fp);
return(0);
}
This was a quick hit at the code from memory. I don't have a compiler readily available but I think it is correct.

Resources