unable to store read characters in a string (C++) - concatenation

I am trying to read text in a file and store it in a string so that it can be output and read
although when I try to see the output string it seems to have a completely different output.
does anyone know why and what I can do to fix it?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <string>
#pragma warning(disable:4996)
using namespace std;
int main()
{
char str=' ';
string myString = "";
FILE* filepointer = fopen("C:/Users/user/Desktop/textfile.txt", "r");
if (filepointer == NULL) {
printf("Can't open file\n");
}
else {
while (!feof(filepointer)) {
str=fgetc(filepointer);
printf("%c",str);
myString = myString + str;
}
fclose(filepointer);
printf("\n\rmyString = %s ", myString);
}
}
to be clear the content in the file is
t
te
tes
test
testi
testin
testing
this is the
code output

you are trying to printf an std::string.
This doesn't work, because, since printf is a c function, it doesn't know about c++ strings.
You could use std::cout << myString << std::endl Or use the c_str() member function of myString to convert it to an c-style string.
printf("\n\rmyString = %s ", myString.c_str());
While the compiler accepts it just fine, it is usually things like this that makes people tell you not to mix c and c++.

Related

C Using char* in fscanf causing error Segmentation fault: 11

I am new to C and I came across an issue when using fscanf to read all strings from a .txt file.
The code is as follow:
#include <stdlib.h>
#include <stdio.h>
int main() {
FILE *spIn;
char *numIn;
spIn = fopen("data.txt", "r");
if (spIn == NULL) {
printf("Can't Open This File \n");
}
while ((fscanf(spIn, "%s", numIn)) == 1) {
printf("%s\n", numIn);
};
fclose(spIn);
return 1;
}
This throws an error: Segmentation fault: 11.
The original data on txt file is:
1 2 345 rrtts46
dfddcd gh 21
789 kl
a mix of ints, strings, white space and newline characters.
At least 4 candidate undefined behaviors (UB) that could lead to a fault of some kind.
Code fails to pass to fscanf(spIn,"%s",numIn) an initialized pointer.
Code calls fscanf() even if fopen() fails.
Code calls fclose() even if fopen() fails.
No width limit in fscanf(spIn,"%s",numIn)), worse than gets().
Text files really do not have strings ('\0' terminated data) nor int, they have lines (various characters with a '\n' termination).
To read a line in and save as a string, use fgets(). Do not use fscanf() to read lines of data.
#include <stdlib.h>
#include <stdio.h>
int main() {
FILE *spIn = fopen("data.txt", "r");
if (spIn == NULL) {
printf("Can't Open This File \n");
} else {
char buf[100];
while (fgets(buf, sizeof buf, spIn)) {
printf("%s", buf);
}
fclose(spIn);
}
}
char* numIn is a pointer, and it is uninitalized, you can't really store anything in it, you need to either allocate memory for it or make it point to some valid memory location:
#include<stdlib.h> // for malloc
char* numIn = malloc(100); // space for 99 char + null terminator byte
//...
while ((fscanf(spIn, "%99s", numIn)) == 1)
{
printf("%s\n",numIn);
};
Or:
char str[100];
char *numIn = str;
Which in this small code makes little sense, you should probably make numIn a fixed size array to begin with:
char numIn[100];
Note that that you should use a width specifier in *scanf to avoid buffer overflow. This still has a problem though, it will read word by word, instead of line by line.
Looking at your input file, using fgets seems like a better option, it can read complete lines, including spaces:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *spIn;
char numIn[100];
spIn = fopen("data.txt", "r");
if (spIn != NULL)
{
while ((fgets(numIn, sizeof numIn, spIn)))
{
numIn[strcspn(numIn, "\n")] = '\0'; // removing \n
printf("%s\n", numIn);
}
fclose(spIn);
}
else
{
perror("Can't Open This File");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Since fgets also parses the \n character, I'm removing it with strcspn.
Though you do verify the return value of fopen the execution continues even if it fails to open, I also addressed that issue.

How to write text containing newline given as command line arguments in C?

I want to create a text file with mulitple lines using system calls in C and populate it with the text provided as command line arguments.
This is what I wrote:
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_SZ 1024
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Invalid Number of arguments\n");
printf("USAGE: ./a.out file_name \"msg\"\n");
} else {
int fd_creat, fd_open, fd_write;
char file_name[MAX_SZ];
char *msg = (char *)malloc(strlen(argv[2]) * sizeof(char));
strcpy(file_name, argv[1]);
fd_creat = creat(file_name, 0777);
if (fd_creat < 2) {
printf("ERROR: File could not be created\n");
} else {
fd_open = open(file_name, O_WRONLY);
strcpy(msg, argv[2]);
fd_write = write(fd_open, msg, strlen(msg));
close(fd_open);
}
}
return 0;
}
If I execute this program as:
./a.out test.txt "Foo\nBar"
It writes the whole thing into test.txt as it is. Basically, I want 'Foo' and 'Bar' in their separate lines.
There's two problems here:
The way you're handling arguments and failing to allocate enough memory for the data involved,
Interpreting escape sequences like \n correctly since the shell will give them to you as-is, raw.
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
// This moves overlapping strings from src -> dest but only
// if dest is before src
void cc_str_drag(char* dest, char* src) {
while (*dest) {
*dest = *src;
++dest;
++src;
}
}
// This interprets the \n sequence and can be extended to handle others, like
// \t, \\, or even \g.
void cc_interpret(char* str) {
for (;*str; ++str) {
// If this is a sequence start...
if (*str == '\\') {
// ...find out which one...
switch (str[1]) {
case 'n':
// Shift back...
cc_str_drag(str, &str[1]);
// ...and replace it.
*str = '\n';
break;
}
}
}
}
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Invalid Number of arguments\n");
// Remember argv[0] is the name of the program
printf("USAGE: %s file_name \"msg\"\n", argv[0]);
return -1;
}
// Since it's not the 1970s, use fopen() and FILE*
FILE* output = fopen(argv[1], "w");
if (!output) {
printf("ERROR: File could not be created\n");
return -2;
}
// Copying here to avoid tampering with argv
char* str = strdup(argv[2]);
// Replace any escape sequences
cc_interpret(str);
// Then just dump it directly into the file
fwrite(str, 1, strlen(str), output);
fclose(output);
return 0;
}
Note the tools used here:
strdup is a way quicker method of copying a C string than malloc(strlen(s)) and then copying it. That's asking for dreaded off-by-one errors.
FILE* performs much better because it's buffered. open() is used for low-level operations that can't be buffered. Know when to use which tool.
Don't be afraid to write functions that manipulate string contents. C strings are really important to understand, not fear.

Using fscanf to store words from file in an array

I am trying to write a program for some classwork that reads in a file using fscanf, and then stores each word into an array with one word in each element. Then I need to print each element of the array out on to a new line on the console.
The getty.txt file has the Gettysburg address in it with appropriate spacing, punctuation, and is multiline.
What I think is happening is that the entire text is being stored in the first element of the array, but I am not 100% sure as I am still learning to debug and write in C.
Any advice as to what I am doing wrong would be great! I currently only seem to be getting the last word and some extra characters.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void readFile();
void writeFile(char* buffer, int bufferlen);
FILE *fpread;
FILE *fpwrite;
char filebuffer[1000];
int filebufferlen = 0;
int main(int argc, char *argv[]) {
fpwrite = fopen("csis.txt", "w");
readFile();
writeFile(filebuffer, filebufferlen);
fclose(fpwrite);
return 0;
}
void readFile() {
char c;
filebufferlen = 0;
if(!(fpread = fopen("getty.txt", "r"))){
printf("File %s could not be opened. \n", "getty.txt");
fprintf(fpwrite,"File %s could not be opened. \n", "getty.txt");
exit(1);
}
while (!feof(fpread)) {
fscanf(fpread, "%s", filebuffer);
filebufferlen++;
}
}
void writeFile(char* filebuffer, int filebufferlen) {
for (int i = 0; i < filebufferlen; ++i){
printf("%c\n", filebuffer[i]);
}
}
After fixing the compile problems:
the code does not contain any code nor data declarations to contain an array of 'words.' So naturally, nothing but the last word is actually saved so it can be printed out.

Data entry into array of character pointers in C

this is my first question asked on here so if I'm not following the formatting rules here please forgive me. I am writing a program in C which requires me to read a few lines from a file. I am attempting to put each line into a cstring. I have declared a 2D character array called buf which is to hold each of the 5 lines from the file. The relevant code is shown below
#include <stdlib.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/un.h> /* UNIX domain header */
void FillBuffersForSender();
char buf[5][2000]; //Buffer for 5 frames of output
int main()
{
FillBuffersForSender();
return 0;
}
void FillBuffersForSender(){
FILE *fp;
int line = 0;
char* temp = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("frames.txt", "r");
printf("At the beginning of Fill Buffers loop.\n");
//while ((read = getline(&temp, &len, fp)) != -1){
while(line < 5){
//fprintf(stderr, "Read in: %s\n", temp);
fgets(temp, 2000, fp);
strcpy(buf[line], temp);
line++;
fprintf(stderr, "Line contains: %s.\n", temp);
temp = NULL;
}
while(line != 0){
fprintf(stderr, "Line contains: %s.\n", buf[line]);
line--;
}
}
The line
strcpy(buf[line], temp);
is causing a segmentation fault. I have tried this numerous ways, and cannot seem to get it to work. I am not used to C, but have been tasked with writing a bidirectional sliding window protocol in it. I keep having problems with super basic issues like this! If this were in C++, I'd be done already. Any help anyone could provide would be incredible. Thank you.
temp needs to point to an allocated buffer that fgets can write into.
In C programming, error checking is an important part of every program (in fact sometimes it seems like there's more error handling code than functional code). The code should check the return value from every function to make sure that it worked, e.g. if fopen returns NULL then it wasn't able to open the file, likewise if fgets returns NULL it wasn't able to read a line.
Also, the code needs to clean up after itself. For example, there is no destructor that closes a file when the file pointer goes out of scope, so the code needs to call fclose explicitly to close the file when it's finished with the file.
Finally, note that many of the C library functions have quirks that need to be understood, and properly handled. You can learn about these quirks by reading the man pages for the functions. For example, the fgets function will leave the newline character \n at the end of each line that it reads. But the last line of a file may not have a newline character. So when using fgets, it's good practice to strip the newline.
With all that in mind, the code should look like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLINE 5
#define MAXLENGTH 2000
static char buffer[MAXLINE][MAXLENGTH];
void FillBufferForSender(void)
{
char *filename = "frames.txt";
FILE *fp;
if ((fp = fopen(filename, "r")) == NULL)
{
printf("file '%s' does not exist\n", filename);
exit(1);
}
for (int i = 0; i < MAXLINE; i++)
{
// read a line
if (fgets( buffer[i], MAXLENGTH, fp ) == NULL)
{
printf("file does not have %d lines\n", MAXLINE);
exit(1);
}
// strip the newline, if any
size_t newline = strcspn(buffer[i], "\n");
buffer[i][newline] = '\0';
}
fclose(fp);
}
int main(void)
{
FillBufferForSender();
for (int i = 0; i < MAXLINE; i++)
printf("%s\n", buffer[i]);
}
Note: for an explanation of how strcspn is used to strip the newline, see this answer.
When it comes to C you have to think of the memory. Where is the memory for a point with NULL assigned to it? How can we copy something to somewhere that we have no space for?

C open() returns -1 for a path string

when i use open() as
int ff=open("/home/user/desktop/bla/test",O_RDONLY);
it works fine.
but when i use a string as the (same path stored in a string) path it doesn't work.
int ff=open(string,O_RDONLY);
why is this?
this is my whole code. i'm confused. i know it should work. but i doesn't. i can't find the bug.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
void bla(char *);
int main(void)
{
// int i;
FILE * fp=fopen("path","r");
char line[256];
while( fgets(line,255,fp)!=NULL){
bla(line);
}
return 0;
}
void bla(char * line){
int status;
printf("%s",line);
pid_t pid=fork();
char string[256];
if(pid==0){
pid=wait(&status);
int ff=open(line,O_RDONLY);
if(ff<0){
printf("\topen error!\n\n");
return;}
int ret=read(ff,string,255);
if(ret<0){
printf("read error!\n");
return;}
printf("%s",string);
close(ff);
exit(0);
}
if (pid>0){
return;
}
}
in bla function, if i replace 'line' with the path, it works. i used a printf to make sure. path is the same (it seems the same).
I call shenanigans :-)
Obviously, if string were exactly the same value as your string literal, and all others things remained the same, it would work fine.
So, if all other things are the same, string is obviously not set to the value you think it is, to wit "/home/user/desktop/bla/test".
My advice would be to print it out (along with an error string) to be sure, something like:
fprintf (stderr, "DEBUG: string is [%s]\n", string);
int ff = open (string, O_RDONLY);
if (ff < 0)
perror ("Could not open file");
And, now that you've posted the code, your problem is obvious: fgets() does not remove the trailing newline so, were you to add the code I proposed above, you would see:
DEBUG: string is [/home/user/desktop/bla/test
]
and deduce the problem.
A quick way to fix this is to remove the newline yourself, with something like:
while (fgets (line, 255, fp) != NULL) {
size_t ln = strlen (line); // Add these
if ((ln > 0) && (line[ln-1] == '\n')) // three
line[ln-1] = '\0'; // lines.
bla (line);
}

Resources