How to compose characters into a single string in memory? - c

I am working on a school assignment and I need a little bit of help.
My question is, how can I compose characters that are read in from a file into a single string of memory. Here is what i have so far.
My Code:
#include <stdio.h>
#include <stdlib.h>
char myString;
int main(int argc, char *argv[]){
FILE* fin;
char ch;
fin=fopen(argv[1],"r");
while((ch=fgetc(fin))!=EOF){
printf("%c\n", ch);
}
fclose(fin);
return 0;
}
My teacher said the last part of main is to be:
putchar(ā€˜\nā€™);
printf( myString );
return 0;
}
But I'm not sure how to put that within my code. Thank you ahead of time, Im also not looking to be just given the answer if you could help me work it out that would be great thank you again.
Updated code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
FILE* fin;
int i;
char myString[3];
fin=fopen(argv[1],"r");
while(fgets(myString,sizeof(myString), fin)){
putchar('\n');
printf("%c\n", myString[i]);
}
fclose(fin);
return 0;
}
Im unsure if this code is exactly correct. It prints out the items within the file and puts a space between them. and there is an array being used for the string.

Im also not looking to be just given the answer
Fine.
Define a char array (mystring) large enough to hold your string
Define a counter to keep track of the position in the array
At each step store ch into the array
Remember to 0-terminate it (store 0 as the last element).
Things to note:
You will need to learn about realloc and grow the storage as you go if your program is to read arbitrarily long input. Better leave that for later
It's generally unsafe to printf(dynamicstr). What if it contains a "%d" ? It's better to printf("%s", dynamicstr).

You get to learn about memcpy and malloc. They are your friends.
--Jason

You need to read the applicable part of your textbook that explains what a "string" is in C. Without you understanding that, there's almost no way to answer your question without simply doing it for you.
A C "string" is a contiguous chunk of memory containing chars and is NULL terminated. You'll need to allocate that then place the characters into it as you read them from the file. Note that you have to make sure you don't go beyond the memory you've allocated while doing so, this is called a "buffer overflow".

#include <stdio.h>
#include <stdlib.h>
char* myString;
int main(int argc, char *argv[]){
FILE* fin;
fpos_t fsize = 0;
char ch;
char *pch;
fin=fopen(argv[1],"r");
fseek(fin,0,SEEK_END);
fgetpos(fin, &fsize);
rewind(fin);
pch = myString = (char*)malloc((fsize+1)*sizeof(char));
while((ch=fgetc(fin))!=EOF){
*pch++ = (char)ch;
}
*pch = '\0';
fclose(fin);
printf("%s", myString);//printf(myString);// need escape %
free(myString);
return 0;
}

Related

How do I properly call the function I created to the main?

So I suck with functions and need to debug this. Im pretty sure the function ToPigLating does its job well at converting. However I just need help calling the function ToPigLatin inside of my main function. But when I try doing that I just get a bunch of error codes.
#include <stdlib.h>
#include <string.h>
#define LEN 32
char* ToPigLatin(char* word[LEN]){
char word[LEN];
char translation [LEN];
char temp [LEN];
int i, j;
while ((scanf ("%s", word)) != '\0') {
strcpy (translation, word);
//just pretend I have all the work to convert it in here.
} // while
}
int main(){
printf("Enter 5 words: ");
scanf("%s", word);
ToPigLatin();
}```
Roughly, variables only exist within the function they're declared in. The word in ToPigLatin exists only within ToPigLatin. It is not available in main. This lets us write functions without worrying about all the rest of the code.
You need to declare a different variable in main, it can also be called word, to store the input and then pass that into ToPigLatin.
Let's illustrate with something simpler, a function which doubles its input.
int times_two(int number) {
return number * 2;
}
We need to give times_two a number.
int main() {
// This is different from "number" in times_two.
int number = 42;
// We have to pass its value into time_two.
int doubled = times_two(number);
printf("%d doubled is %d\n", number, doubled);
}
Your case is a bit more complicated because you're working with input and memory allocation and arrays. I'd suggest just focusing on arrays and function calls for now. No scanf. No strcpy.
For example, here's a function to print an array of words.
#include <stdio.h>
// Arrays in C don't store their size, the size must be given.
void printWords(const char *words[], size_t num_words) {
for( int i = 0; i < num_words; i++ ) {
printf("word[%d] is %s.\n", i, words[i]);
}
}
int main(){
// This "words" variable is distinct from the one in printWords.
const char *words[] = {"up", "down", "left", "right"};
// It must be passed into printWords along with its size.
printWords(words, 4);
}
ToPigLatingToPigLating function expects to have a parameter like ToPigLating("MyParameter");
Hello there icecolddash.
First things first, there are some concepts missing. In main section:
scanf("%s", word);
You're probably trying to read a string format and store in word variable.
In this case, you should have it on your declaration scope. After some adjustment, it will look like this:
int main(){
char word[LEN];
As you defined LEN with 32 bytes maximum, your program will not be allowed to read bigger strings.
You're also using standard input and output funcitions as printf, and so you should ever include stdio.h, thats the header which cointains those prototypes already declared, avoiding 'implicit declaration' compiling warnings.
Next issue is how you're declaring your translation function, so we have to think about it:
char* ToPigLatin(char* word[LEN])
In this case, what you wrote:
ToPigLatin is a funcion that returns a char pointer, which means you want your function to probably return a string. If it makes sense to you, no problem at all. Although we got some real problem with the parameter char* word[LEN].
Declaring your variable like this, assume that you're passing an array of strings as a parameter. If I got it right, you want to read all five words in main section and translate each one of them.
In this case I suggest some changes in main function, for example :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 32
#define MAX_WORDS 5
char *globalname = "translated";
char* ToPigLatin(char* word){
char *translation = NULL;
//Translation work here.
if ( !strcmp(word, "icecolddash") ){
return NULL;
}
translation = globalname;
return translation;
}
int main(){
char word[LEN];
char *translatedword;
int i;
printf("Enter 5 words: \n");
for ( i=0; i < MAX_WORDS; i++ ){
fgets(word, sizeof(word), stdin);
strtok(word, "\n"); // Just in case you're using a keyboard as input.
translatedword = ToPigLatin(word);
if ( translatedword != NULL ){
//Do something with your translation
//I'll just print it out as an example
printf("%s\n", translatedword);
continue;
}
// Generic couldn't translate message
printf("Sorry, I know nothing about %s\n", word);
}
return 0;
}
The above code translate every word in a fixed word "translated".
In case of reading the exact input "icecolddash", the program will output a generic error message, simulating some problem on translation process.
I hope this help you out with your studies.
There are a few things that I see.
#include <stdio.h>
#include <stdlib.h>
char* ToPigLatin(char* word){
printf(word);
return word;
}
int main(){
printf("Enter 5 words: ");
// declare the variable read into by scanf
char * word = NULL;
scanf("%s", word);
//Pass the variable into the function
ToPigLatin(word);
// Make sure you return an int from main()
return 0;
}
I left some comments in the code with some specific details.
However, the main thing that I would like to call out is the style of the way you're writing your code. Always try to write small, testable chunks and build your way up slowly. Try to get your code to compile. ALWAYS. If you can't run your code, you can't test it to figure out what you need to do.
As for the char ** comment you left on lewis's post, here is some reading you may find useful in building up your intuition:
https://www.tutorialspoint.com/what-does-dereferencing-a-pointer-mean-in-c-cplusplus
Happy coding!

How to concatenate char pointers using strcat in c? [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 3 years ago.
I'm learning pointers in C, using Linux. I'm trying to use the strcat function, but it doesn't work and I don't understand why.
I'm passing a username to the main as an argument because I need to concatenate and put a number 1 in the first position of this username. For example if the I got as argument username123 I need to convert this to 1username123
I got this code:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
const char *userTemp;
char *finalUser;
userTemp = argv[1]; //I got the argument passed from terminal
finalUser = "1";
strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
printf("User: %s\n",finalUser);
return 0;
}
The code compiles, but I got a segmentation fault error and doesn't know why. Can you please help me going to the right direction?
It is undefined behaviour in C to attempt to modify a string literal (like "1"). Often, these are stored in non-modifiable memory to allow for certain optimisations.
Let's leave aside for the moment the fact that your entire program can be replaced with:
#include <stdio.h>
int main(int argc, char *argv[]){
printf("User: 1%s\n", (argc > 1) ? argv[1] : "");
return 0;
}
The way you ensure you have enough space is to create a buffer big enough to hold whatever you want to do. For example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
// Check args provded.
if (argc < 2) {
puts("User: 1");
return 0;
}
// Allocate enough memory ('1' + arg + '\0') and check it worked.
char *buff = malloc(strlen(argv[1]) + 2);
if (buff == NULL) {
fprintf(stderr, "No memory\n");
return 1;
}
// Place data into memory and print.
strcpy(buff, "1");
strcat(buff, argv[1]);
printf("User: %s\n", buff);
// Free memory and return.
free(buff);
return 0;
}
What you shouldn't do is to allocate a fixed size buffer and blindly copy in the data provided by a user. That's how the vast majority of security problems occur, by people overwriting buffers with unexpected data.
I'm trying to use the strcat function, but it doesn't work and I don't understand why.
For starters, you really shouldn't use strcat(). Use strlcat() instead. The "l" version of this and other functions take an extra parameter that let you tell the function how large the destination buffer is, so that the function can avoid writing past the end of the buffer. strcat() doesn't have that parameter, so it relies on you to make sure the buffer is large enough to contain both strings. This is a common source of security problems in C code. The "l" version also makes sure that the resulting string is null-terminated.
The code compiles, but I got a segmentation fault error and doesn't know why.
Here's the prototype for the function: char *strcat( char *dest, const char *src );
Now, you're calling that essentially like this: strcat("1", someString);. That is, you're trying to append someString to "1", which is a string constant. There's no extra room in "1" for whatever string is in someString, and because you're using a function that will happily write past the end of the destination buffer, your code is effectively writing over whatever happens to be in memory next to that string constant.
To fix the problem, you should:
Switch to strlcat().
Use malloc() or some other means to allocate a destination buffer large enough to hold both strings.
Unlike in other languages there is no real string type in C.
You want this:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
const char *userTemp;
char finalUser[100]; // finalUser can contain at most 99 characters
userTemp = argv[1]; //I got the argument passed from terminal
strcpy(finalUser, "1"); // copy "1" into the finalUser buffer
strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
printf("User: %s\n",finalUser);
return 0;
}
or even simpler:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
char finalUser[100]; // finalUser can contain at most 99 characters
strcpy(finalUser, "1"); // copy "1" into the finalUser buffer
strcat(finalUser, argv[1]); //To concatenate argv[1] to finalUser
printf("User: %s\n",finalUser);
return 0;
}
Disclaimer: for the sake of brevity this code contains a fixed size buffer and no check for buffer overflow is done here.
The chapter dealing with strings in your C text book should cover this.
BTW you also should check if the program is invoked with an argument:
int main(int argc, char *arg[]){
if (argc != 2)
{
printf("you need to provide a command line argument\n");
return 1;
}
...
You're missing some fundamentals about C.
finalUser = "1";
This is created in "read-only" memory. You cannot mutate this. The first argument of strcat requires memory allocated for mutation, e.g.
char finalUser[32];
finalUser[0] = '1';

Save command line argument as global variable in C

I'm trying to read in two filenames and save them as a global variable in C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char infilename;
char outfilename;
int main(int argc, const char* argv[]){
strcopy(infilename, argv[1]);
return 0;
}
However this does not work. Can someone help me with a really simple problem like this?
You are trying to copy a string (const char *) to a character (char). You need to either declare infilename as a string:
char *infilename;
infilename = malloc(...
or make a static array:
char infilename[NUM_OF_CHARS];
Read up on c strings here.
Also choose your language, if you are really using c++ you need to start using std::string
A better way to do it.
char infilename[50];
char outfilename[50];
int main(int argc, const char* argv[]){
if(argc == 3)
{
strcpy (infilename,argv[1]);
strcpy (outfilename,argv[2]);
}
else
{
//do something else
}
return 0;
}
You need array of char and not only char. A string in C is an array of char. And you must always verify (if(argc == 3) if the user entered the quantity of argument you want, because if it's not the case your applicatin can crash.
That's not going to work.
These:
char infilename;
char outfilename;
declare a variables that store a single char, not an entire string.
You either need to make those char arrays:
char infilename[MAX_PATH];
char outfilename[MAX_PATH];
or pointers that you plan to initialize with malloced memory. You have to pick which one you mean.
P.s. there's no function called strcopy, it's strcpy.
The main problem is that you made your global variables single characters not an array of characters which is needed for a string.
Assuming you don't want to change the contents of the string then the easiest thing is to simply set a global to point to the same string rather than copying it. Because the program will end when main returns there is no worry about the parameters argv going out of scope.
Note you would have to worry about this if you create a new thread and terminate the thread running main without terminating the program.
#include <stdio.h>
#include <stdlib.h>
static char* gInFilenamePtr;
static char* gOutFilenamePtr;
int main(int argc, const char* argv[])
{
if( argc > 2 )
{
gInFilenamePtr = argv[1];
gOutFilenamePtr = argv[2];
}
return 0;
}

Getting a segmentation fault when trying to use strcpy() to a 2D char array?

I'm trying to write a function that takes in two strings, concatenates them, and then writes them to a 2D array. I have been messing around with different things and looking at other posts to no avail. The seg fault seems to occur in the last strcpy when I'm trying to write the the concatenated string to the char array. If that line is commented out the program seems to work just fine.
void saveToArray(char *command1, char *command2)
{
char *saveCommands[30][100];
int *commands = malloc(sizeof(int));
char concatCommand[30];
strcpy(concatCommand, command1);
strcat(concatCommand, " ");
strcat(concatCommand, command2);
strcpy(*&saveCommands[0][*commands], concatCommand);
*commands += 1;
}
I apologize in advance for any formatting issues as this is my first post and thanks for any answers!
There are a number of scary things going on in this function. For starters...
int *commands = malloc(sizeof(int));
You don't free this or return it, so it is 100% a memory leak. I see no reason why you should want to allocate this integer on the heap rather than the stack.
char concatCommand[30];
strcpy(concatCommand, command1);
strcat(concatCommand, " ");
strcat(concatCommand, command2);
This could potentially overflow your buffer.
strcpy(*&saveCommands[0][*commands], concatCommand);
*& is a no-op (it doesn't do anything). You don't copy anything into commands, so *commands could be anything. Finally, the pointers in saveCommands aren't initialized so strcpy(saveCommands[x][y], "some string") will basically always segfault in practice. I think you might want this instead:
char saveCommands[30][100]
...
strcpy(&saveCommands[0][*commands], concatCommand);
I took the liberty to re-write your code a bit... too many characters make my eyes hurt... at any rate, this code works. It was mainly the strcpy dereference that was causing the issue.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void cmds(char *c1, char *c2) {
char sc[30][100];
int c = 0;
char cc[30];
strcpy(cc, c1);
strcat(cc, " ");
strcat(cc, c2);
strcpy(&sc[c][0], cc); // problem was here...
printf("%s\n", &sc[c][0]);
}
int main() {
char *c1 = "c001";
char *c2 = "c002";
cmds(c1, c2);
return 0;
}

How to add a character at end of string

ā€ƒā€ƒI have a file copy program that takes from one file and pastes in another file pointer. But, instead of getting targetname from user input i'd like to just add a '1' at the end of the input filename and save. So, I tried something like this...
.... header & inits ....
fp=fopen(argv[1],"r");
fq=fopen(argv[1].'1',"w");
.... file copy code ....
Yeah it seems stupid but I'm a beginner and need some help, do respond soon. Thanks :D
P.S. Want it in pure C. I believe the dot operator can work in C++.. or atleast i think.. hmm
One more thing, i'm already aware of strcat function.. If i use it, then i'll have to define the size in the array... hmm. is there no way to do it like fopen(argv[1]+"extra","w")
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* stradd(const char* a, const char* b){
size_t len = strlen(a) + strlen(b);
char *ret = (char*)malloc(len * sizeof(char) + 1);
*ret = '\0';
return strcat(strcat(ret, a) ,b);
}
int main(int argc, char *argv[]){
char *str = stradd(argv[1], "extra");
printf("%s\n", str);
free(str);
return 0;
}
Have a look at strcat:
An example:
#include <string.h>
char alpha[14] = "something";
strcat(alpha, " bla"); // "something bla"
printf("%s\n", alpha);
Using the dot won't work.
The function you are looking for is called strcat.
Unfortunately . would not work in c++.
A somewhat inelegant but effective method might be to do the following.
int tempLen=strlen(argv[1])+2;
char* newName=(char*)malloc(tempLen*sizeof(char));
strcpy(newName,argv[1]);
strcat(newName,"1");
In C to concatenate a string use strcat(str2, str1)
strcat(argv[1],"1") will concatenate the strings. Also, single quotes generate literal characters while double quotes generate literal strings. The difference is the null terminator.

Resources