I'm making a program that basically receives 2 files (a .pal and a .dic file) and outputs a file called solution file (blabla.sol). However that solution file's name depends on one of those files that the program received. How can I modify my program in order to change the output file's name depending on the name of the received file's name? In this case I want it to be the same names as my name_pal file.
Here's the program that I've already written (right now, as it is, it only outputs a file with a fixed name):
int main(int argc, char *argv[])
{
char name_dic[MAX_FILENAME_SIZE];
char name_pal[MAX_FILENAME_SIZE];
char name_sol[] = "prob0.sol";
char words_dic[MAX_WORD_SIZE];
char words_pal[MAX_WORD_SIZE];
char word_same_size[MAX_WORD_SIZE];
char dic_total[MAX_DIC_SIZE][MAX_WORD_SIZE];
char pal_total[MAX_PAL_SIZE][MAX_WORD_SIZE];
FILE *dic, *pal, *sol;
if (argc < 3)
{
printf("Missing files.\n");
exit(1);
}
strcpy(name_dic, argv[1]);
strcpy(name_pal, argv[2]);
dic = fopen(name_dic, "r");
if (dic == NULL)
{
printf("Can not open dictionary file: %s\n", name_dic);
exit(1);
}
pal = fopen(name_pal, "r");
if (pal == NULL)
{
printf("Can not open problem file: %s\n", name_pal);
exit(1);
}
sol = fopen(name_sol, "w");
if (sol == NULL)
{
printf("Can not open solution file: %s\n", name_sol);
exit(1);
}
/* rest of the code */
You can write a truncate function at the '.' and then append sol as shown in snippet below.
char name_sol[MAX_FILENAME_SIZE];
int i;
for(i=0;i<MAX_FILENAME_SIZE;i++){
name_sol[i]=name_pal[i];
if(name_sol[i]=='.') break;
}
strcpy(name_sol+i+1,"sol");
printf("%s\n",name_sol);
Related
I have to read a text file, make some trivial transformation character by character (swapping the case of all letters), write results to the text files. I wrote this code, but it's not working. Please guide me in this regard. Thanks for in Advance
#include <stdio.h>
#include <stdlib.h>
int main() {
char c[1000];
char x[100];
char var;
int i;
FILE *fptr;
if ((fptr = fopen("text.txt", "r")) == NULL) {
printf("Error! opening file");
// Program exits if file pointer returns NULL...
exit(1);
}
// reads text until a newline is encountered...
fscanf(fptr, "%[^\n]", c);
printf("Data from the file:\n%s", c);
// Convert the file to upper case....
for( i=0;i<= strlen(c);i++){
if(c[i]>=65&&c[i]<=90)
c[i]=c[i]+32;
}
fptr = fopen("program.txt","w");
fprintf(fptr,"%[^\n]",c);
fclose(fptr);
return 0;
}
Edit: added #include <stdlib.h>, removed static describing main()
My proposition, based on example of copying a file given at my uni.
I used toupper() from ctype.h, if you don't want to use it you can just add 32 under condition similarly to your solution
Note: there could be char c instead of int c. (In the original version it actually was char; I changed it because if you look at the headers in the docs of all functions dealing with c, they all take/return int, not char; in your version it would matter more as you keep an array, in my program it changes pretty much nothing – int is just my preferred practice).
Note2: I actually never delved into the difference between "w"/"r" (write/read) and "wb"/"rb" (write/read binary). The code seems to work either way.
(I think there is no big difference when the files are text files anyway, for further assurance that both versions work, note that the code uses feof() to handle EOF)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
FILE *from, *to;
int c;//could be char
/* opening the source file */
if ((from = fopen("text.txt", "rb")) == NULL) {
printf("no such source file\n");
exit(1);
}
/* opening the target file */
if ((to = fopen("program.txt", "wb")) == NULL) {
printf("error while opening target file\n");
exit(1);
}
while (!feof(from)) {
c = fgetc(from);
if (ferror(from)) {
printf("error while reading from the source file\n");
exit(1);
}
if (!feof(from)) {//we avoid writing EOF
fputc(toupper(c), to);
if (ferror(to)) {
printf("error while writing to the target file\n");
exit(1);
}
}
}
if (fclose(from) == EOF) {
printf("error while closing...\n");
exit(1);
}
if (fclose(to) == EOF) {
printf("error while closing...\n");
exit(1);
}
return 0;
}
For a version taking arguments from command line (works on windows too) replace the beginning of main with
int main(int argc, char *argv[]) {
FILE *from, *to;
char c;
/* checking the number of arguments in the command line */
if (argc != 3) {
printf("usage: name_of_executable_of_this_main <f1> <f2>\n");//name_of_exe could be copy_to_upper, for example; change adequately
exit(1);
}
/* opening the source file */
if ((from = fopen(argv[1], "rb")) == NULL) {
printf("no such source file\n");
exit(1);
}
/* opening the target file */
if ((to = fopen(argv[2], "wb")) == NULL) {
printf("error while opening the target file\n");
exit(1);
}
I don't know how to code in that language(i think it's C++), but basically want you should be doing is a for loop to iterate through every character in the string. In Python it would look like:
x = open("text.txt", "r")
y = open("new text.txt","w")
z = ""
for char in x:
z += char.upper()
y.write(z)
I hope I was able to give an idea of how to solve your problem. I'm a newbie as well, but in Python.
For example I have a text file includes "I'm having great day!", I want to count each character and word in this file.
in the example "there are 3 a, 1 m" etc.
I'm new at C and know how to open a file, how can find a specific char or word in file but couldn't figure this out. Can you help me pls.
The first thing you need to learn is how to open and process a file one character at a time. You can do this with a program like:
#include <stdio.h>
int main(int argc, char *argv[]) {
// Must provide one argument, the file to process.
if (argc != 2) {
fprintf(stderr, "Usage: myprog <inputFileName>\n");
return 1;
}
// Try to open the file.
FILE *inFile = fopen(argv[1], "r");
if (inFile == NULL) {
fprintf(stderr, "Cannot open '%s'\n", argv[1]);
return 1;
}
// Process file, character by character, until finished.
int ch;
while ((ch = fgetc(inFile)) != EOF) {
putchar(ch); // <accumulate>
}
// Close file and exit.
fclose(inFile);
// <output>
return 0;
}
Then it's a matter of changing the putchar call into whatever you need to do (accumulating character counts) and outputting that information before you exit from the main function.
First off I am creating a program that will read lines of characters and find words (they don't have to have meaning, i.e 'ab' could be word ) and storing them in the appropriate data structure. I used trie structure to store the words. I am given a mapping file as a command line argument yet inside the mapping file I have two data files I need to gain information from. The usage interface is as follows: first(program name) <mappingfile>.
Inside the mapping file, there exists two data files: <dictFile> and <dataFile>. Im not sure how to read and store the information presented the two data files. So far I have the following:
#include <stdio.h>
#include<stdlib.h>
void readDict(FILE *dict_file){
}
int main(int argc, char *argv[]){
FILE* file;
if(argc != 2){ //error in inputing, not 2 files
printf("error\n");
return 0;
}
file = fopen(argv[1],"r" ); //reading the mapping file
input;
if(file == NULL){ //nothing inside file
printf("file does not exist\n");
return 0;
}
}
My goal is to have pointers point to respective data files in the mapping file which I can use for reading their contents.
I will be given the following input in the command line:
first(program name) <mappingfile>.
Inisde the mapping file contains the lines of two plain .txt files in the form
<dictFile> <dataFile>.
I wish to access both contents of <dictFile> and <dataFile>.. with pointers to the respective file.
If I understand your question correctly you want to parse a file where each line contains the filenames of two other files and then read from these. What you can do is use fgets to read your mapping file line by line. What you can do next is use the function strtok to split your string on a whitespace. I'll break it down for you step by step.
Firstly we want to open the mapping file for reading
if((file = fopen(argv[1],"r")) == NULL) {
perror("error opening file");
return 1;
}
This will try to open the mapping file specified by the command line arguments of your program and if it fails it will print a corresponding error message.
while(fgets(buf, sizeof(buf), file) != NULL) {
After we've opened the file we want to iterate through all the lines until we reach the end of the file and fgets will return NULL. fgets will put the current line into buf.
dictfilename = strtok(buf, " ");
datafilename = strtok(NULL, " ");
strtok(dictfilename, "\n"); /* Remove any trailing newlines */
strtok(datafilename, "\n");
We need to split the line read by fgets by a delimter (a whitespace) so we know which part corresponds to the dictfile and the datafile. This is done by using the strtok function which returns a pointer to the substring before the whitespace and when passing in NULL it will return a pointer to the substring after the whitespace. A slightly weird way of removing any trailing newlines is to use strtok and the newline as a delimiter.
if((dictfile = fopen(dictfilename,"r")) == NULL) {
fprintf(stderr, "error opening file %s: %s\n", dictfilename, strerror(errno));
return 1;
}
if((datafile = fopen(datafilename,"r")) == NULL) {
fprintf(stderr, "error opening file %s: %s\n", datafilename, strerror(errno));
return 1;
}
Very similiarly to how we open the mapping file, we now open the two files found on the current line read by fgets with "r" mode which opens for reading. If the file does not exist or cannot be found, the fopen call fails.
printf("Content of %s:\n", dictfilename);
while ((c = getc(dictfile)) != EOF)
putchar(c);
printf("\nContent of %s:\n", datafilename);
while ((c = getc(datafile)) != EOF)
putchar(c);
This is a very simple method of "dumping" the content of the files. It uses getc to read the next char from the file and prints it until it reads EOF. This is where you should do your own function.
fclose(dictfile);
fclose(datafile);
And don't forget to close the files afterwards or you will leak resources.
Finally here is the code on what I just described
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define MAX_LENGTH 100 // change this to the actual maximum length of your lines.
int main(int argc, char **argv){
FILE* file, *dictfile, *datafile;
char c;
char buf[MAX_LENGTH];
char *dictfilename, *datafilename;
if(argc != 2) {
fprintf(stderr, "Usage: %s <mapping file>\n", argv[0]);
return 0;
}
if((file = fopen(argv[1],"r")) == NULL) {
perror("error opening file");
return 1;
}
while(fgets(buf, sizeof(buf), file) != NULL) {
dictfilename = strtok(buf, " ");
datafilename = strtok(NULL, " ");
strtok(dictfilename, "\n"); /* Remove any trailing newlines */
strtok(datafilename, "\n");
if((dictfile = fopen(dictfilename,"r")) == NULL) {
fprintf(stderr, "error opening file %s: %s\n", dictfilename, strerror(errno));
return 1;
}
if((datafile = fopen(datafilename,"r")) == NULL) {
fprintf(stderr, "error opening file %s: %s\n", datafilename, strerror(errno));
return 1;
}
// do something with the files (e.g read all the content)
printf("Content of %s:\n", dictfilename);
while ((c = getc(dictfile)) != EOF)
putchar(c);
printf("\nContent of %s:\n", datafilename);
while ((c = getc(datafile)) != EOF)
putchar(c);
printf("\n");
// don't forget to close the files when you're done with them.
fclose(dictfile);
fclose(datafile);
}
fclose(file);
}
If I understand you correctly this should do it. Note that it assumes your filenames don't have any spaces. And if you want to use the "non secure" api's you need to add _CRT_SECURE_NO_WARNINGS to the project properties under Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions.
#include <stdio.h>
#include<stdlib.h>
void readDict(FILE *dict_file){
}
int main(int argc, char *argv[]){
FILE* file;
if(argc != 2){ //error in inputing, not 2 files
printf("error\n");
return 1;
}
file = fopen(argv[1],"r" ); //reading the mapping file
//input;
if(file == NULL){ //nothing inside file
printf("file does not exist\n");
return 1;
}
char dictFileString[256], dataFileString[256];
fscanf( file, "%255s %255s", dictFileString, dataFileString );
FILE *dictFile, *dataFile;
dictFile = fopen( dictFileString, "r" );
if (dictFile == NULL) {
printf( "%s does not exist\n", dictFileString );
fclose(file);
return 1;
}
dataFile = fopen( dataFileString, "r" );
if (dataFile == NULL) {
printf( "%s does not exist\n", dataFileString );
fclose(file);
fclose(dictFile);
return 1;
}
readDict(dictFile);
// The additional logic would be placed here.
fclose( dictFile );
fclose( dataFile );
// If you need to read additional file names then loop
// back up to read the next line of 'file'
fclose( file );
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int ch; //place to store each character as read
FILE *fp;
unsigned long count = 0;
if (argc != 2)
{
printf("Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
printf("Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
while ((ch = getc(fp)) != EOF)
{
putc(ch,stdout); // same as putchar(ch);
count++;
}
fclose(fp);
printf("File %s has %lu characters\n", argv[1], count);
return 0;
}
The result running this program is:
Usage: /Users/huangweijun/Library/Developer/Xcode/DerivedData/input-hhjvfzwnywskidbyoxavtgvmoffb/Build/Products/Debug/input filename
I don't know which step is wrong.
The problem is you need to pass exaclty 1 argument to your program on invokation, to achieve that in XCode you neet to go to thes menu
Product -> Edit Scheme... -> Run -> Arguments
and there you will see Arguments Passed On Launch click the plus sign, and then add a file name, the path to the file you wish to open.
Or you can ask the user for a file name like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int ch; //place to store each character as read
FILE *fp;
unsigned long count = 0;
const char *filename;
char buffer[128];
filename = NULL;
if (argc != 2)
{
size_t length;
printf("Enter the file name > ");
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
return -1; // error or end of file sent to the terminal
length = strlen(buffer);
if (buffer[length - 1] == '\n') // remove the traling '\n' add by fgets
buffer[length - 1] = '\0';
filename = buffer;
}
else
filename = argv[1];
if ((fp = fopen(filename, "r")) == NULL)
{
printf("Can't open %s\n", filename);
exit(EXIT_FAILURE);
}
while ((ch = getc(fp)) != EOF)
{
putc(ch,stdout); // same as putchar(ch);
count++;
}
fclose(fp);
printf("File %s has %lu characters\n", filename, count);
return 0;
}
You are not providing enough command line arguments. To provide an input file in xcode, you can go to the Product Menu -> Scheme -> Edit Scheme option.... at this point you can pass in the path to the file you wish to use as input
Your program is working as it is supposed to. You are not providing the command line argument and it is telling you so
The Screen for adding arguments in xcode looks like what I am showing below. You get to this screen, using the menu options described above, click the plus button, then added the path to the input file
There's nothing wrong. Read the code, especially this part:
if (argc != 2)
{
printf("Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
If the number of command-line arguments is not equal to 2, print out some usage information then exit. So you need to invoke the program with a single command-line argument.
Note that although it compares to the value 2, the program needs only 1 argument, since the program name itself counts as the first argument, i.e. argv[0].
Product -> Edit Scheme... -> Run -> Arguments
in "Arguments Passed On Launch" click the plus sign, and then add an absolute file name, the path to the file you wish to open.
***If your folder names, in your absolute path, have spaces THIS WILL NOT WORK!. Therefore open up terminal, drag and drop your file in the terminal window then copy the absolute path (from the terminal window of course) and paste it in "Arguments Passed On Launch" section (as explained above).
I wish I could i could give more information, but I genuinely have no idea what is going on here. This code opens files for appension or overwriting, depending on user arguments (appension by default). It gets as far as the fgets for user input, and then as soon as the input is entered, it segfaults and dumps core. This is strange, because before I implemented arguments (i.e. it was just ./a.out file) it worked fine, so I guess it has something to do with the new stuff about arguments...
#include <stdio.h>
#include <string.h>
int printhelp(void);
int main(int argc, char *argv[])
{
char input[256];
int loopstat = 0;
FILE *inputfile;
if (argc < 2) /* Check argc for minimum 2 arguments (i.e. cw FILE) */
{
printf("ca: missing file operand\n");
return 0;
}
else if (argc > 2) /* Check argc for more than 2 arguments (i.e. cw -o FILE) */
{
if (strncmp(argv[1], "-", 1) == 0) /* if first argument begins with "-", it must be an option, so descend into option checking */
{
if (strcmp(argv[1], "-a") == 0) /* If -a option is given, open for appending */
{
FILE *inputfile = fopen(argv[2], "a");
}
else if (strcmp(argv[1], "-o") == 0) /* If -o option is given, open for overwriting */
{
FILE *inputfile = fopen(argv[2], "w");
}
else if (strcmp(argv[1], "--help") == 0) /* If --help option is given, print help and quit */
{
printhelp();
return 0;
}
else
{
printf("cw: invalid option\n"); /* If invalid option is given, print the fact and quit*/
return 0;
}
}
}
else /* if argc is equal to 2 (i.e. "cw FILE" or "cw -o")...*/
{
if (strncmp(argv[1], "-", 1) == 0) /* Check if user has specified an option but no file (i.e. "cw -o") */
{
printf("cw: missing file operand\n"); /* If they have, print that no file is spec'd and quit */
return 0;
}
else /* If not, it's a legit file with no other arguments (e.g. "cw FILE") so open it in append mode by default */
{
FILE *inputfile = fopen(argv[2], "a");
}
}
/* Writing loop */
printf("Enter input...\n");
while (loopstat == 0) /* Get user input and write to file until they give exit command */
{
fgets(input, 256, stdin); /* Get user input */
if (strcmp(input, ":x\n") == 0) /* If input == exit command, quit */
{
printf("co: exit received, terminating...\n");
loopstat++;
}
else /* Write to file */
{
fprintf(inputfile, "%s", input);
}
}
fclose(inputfile);
}
int printhelp(void) /* Print help on --help command */
{
printf(
"Usage: ca FILE\nContinuously append input to the FILE\nca does not currently support multiple file appension.\nReport bugs to scamp#lavabit.com\n");
return 0;
}
P.S. sorry if I messed up the indentation, it's really confusing to have to add four spaces before everything in this much code.
Here you are shadowing your variable:
else /* If not, it's a legit file with no other arguments (e.g. "cw FILE") so open it in append mode by default */
{
FILE *inputfile = fopen(argv[2], "a");
}
should be
else /* If not, it's a legit file with no other arguments (e.g. "cw FILE") so open it in append mode by default */
{
inputfile = fopen(argv[2], "a");
}
You have several instances like this, so remove the declaration there as well.
You are declaring the identifier inputfile several times, but it won't be the same object at each time.
See the behavior of this program for instance (from Wikipedia):
#include <stdio.h>
int main(void)
{
char x = 'm';
printf("%c\n", x);
{
printf("%c\n", x);
char x = 'b';
printf("%c\n", x);
}
printf("%c\n", x);
}
You have to declare inputfile just once, and then assign it in if statements.
FILE *inputfile;
if (/* ... */)
inputfile = /* ... */
else if (/* ... */)
inputfile = /* ... */
else
inputfile = /* ... */
int main(int argc, char *argv[])
{
char input[256];
int loopstat = 0;
FILE *inputfile;
then you have:
if (strcmp(argv[1], "-a") == 0)
{
FILE *inputfile = fopen(argv[2], "a");
}
You should not redeclare a new object inputfile but reuse your inputfile declared at the top of your function.
Example:
inputfile = fopen(argv[2], "a");
The problem is there:
FILE *inputfile;
....
if (strcmp(argv[1], "-a") == 0)
{
FILE *inputfile = fopen(argv[2], "a");
}
By writing this way you are hiding the variable inputfile from the compiler. Thus the variable defined in the beginning stays uninitialized.
You should write it following way:
if (strcmp(argv[1], "-a") == 0)
{
inputfile = fopen(argv[2], "a");
}
So now you will use the variable defined in the top of the function.
You should read about the variable scope.