How can I remove the "#" from "#2" is a .asm file? My output is currently incorrect when read from the file, but when using just "2" it produces the proper binary result.
FILE *fp;
char buffer[256];
fp = fopen("Add.asm", "r");
if(fp == NULL){
printf("Error opening file\n");
}
else{
while(fgets(buffer, 256, fp) != NULL){
buffer[strcspn(buffer, "\r\n")] = 0;
printf("Buffer:");
printf("%s\n",buffer);
if(aOrC(buffer) == true){
int changer = stringToInt(buffer);
printf("%s\n",intToBinary(changer));
} else if(aOrC(buffer) == false){
char* jump = jumpBits(buffer);
char* dest = destBits(buffer);
char* comp = compBits(buffer);
char* finalBits = finalBinaryC(comp, dest, jump);
printf("%s\n", finalBits);
}
}
fclose(fp);
}
The Add.asm file is below and from the nand2tetris project.
#2
D=A
#3
D=D+A
#0
M=D
Based on your output the # comes always at the beginning of the strings. So
you can easily do this:
// str contains the string "#2"
puts(str + (str[0] == '#' ? 1 : 0));
If you want to remove a # at some random position, then you should write a
function like this
char *remove_char(char *src, char c)
{
if(src == NULL)
return NULL;
char *p = strchr(src, c);
if(p == NULL)
return src; // c not found
// removing c
memmove(p, p+1, strlen(p));
return src;
}
Then you can call it like
char line[] = "abc#def";
puts(remove_char(line, '#'));
This would print abcdef
Related
I have a text file, "input", in which some lines contain the character '$'. I want to copy this file into a new text file, "output", but with all the lines truncated after (and including) the '$' character (if present).
I have tried the following:
while (fgets(line, LINE_LENGTH, input) != NULL)
{
strcpy(tmp_line, line);
cmt_ptr = strchr(tmp_line, '$');
if (cmt_ptr != NULL)
{
*cmt_ptr = '\n';
}
fputs(tmp_line, output);
}
This compiles, but all the text after '$' in each line gets copied into a new line.
I then tried this:
while (fgets(line, LINE_LENGTH, input) != NULL)
{
strcpy(tmp_line, line);
cmt_ptr = strchr(tmp_line, '$');
if (cmt_ptr != NULL)
{
strtok(tmp_line, '$');
}
fputs(tmp_line, output);
}
but I get an error message saying "Access violation reading location".
Can someone please advise me on how to correct the code?
Below code is insufficient as only the $ is substituted with a '\n'. To shorten the string, set a null character. #Some programmer dude
if (cmt_ptr != NULL)
{
*cmt_ptr = '\n';
cmt_ptr[1] = '\0'; // Add
}
Alternative approach: Use different ways to print when a $ is found. No tmp_line needed.
while (fgets(line, LINE_LENGTH, input) != NULL) {
char *cmt = strchr(line, '$');
if (cmt) {
int length = cmt - line;
printf("%.*s\n", length, line); // Print limited character array.
} else {
fputs(line, output);
}
}
Using fgets is over-complicating the issue, since there's no need to read full lines. Just read one character at a atime. eg:
#include <stdlib.h>
#include <stdio.h>
FILE * xfopen(const char *path, const char *mode);
int
main(int argc, char **argv)
{
FILE *input = argc > 1 ? xfopen(argv[1], "r") : stdin;
FILE *output = argc > 2 ? xfopen(argv[2], "w") : stdout;
enum { print, noprint } state = print;
int c;
while( (c = getc(input)) != EOF ){
switch( c ){
case '$':
state = noprint;
break;
case '\n':
state = print;
}
if( state == print ){
putc(c, output);
}
}
return 0;
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
I've been trying to merge the contents of two .txt files into a third .txt file that combines the output. All I know how to do (and all I have been able to find answers for), however, is to merge them by putting the contents of the first file first, and the second file second. However, I would prefer the output to list the first line of the first file, then the first line of the second file -- followed on a new line by the second line of the first file and the second line of the second file.
To make this clearer visually, the code is currently appearing as:
file1-line1
file1-line2
file1-line3
file2-line1
file2-line2
file2-line3
... When I'd like it to appear as:
file1-line1 file2-line1
file1-line2 file2-line2
file1-line3 file2-line3
The code I have is very basic and executes the first example fine:
int main()
{
FILE *pointer1 = fopen("file1.txt", "r");
FILE *pointer2 = fopen("file2.txt", "r");
FILE *pointer3 = fopen("combined.txt", "w");
int ch;
if (pointer1 == NULL || pointer2 == NULL || pointer3 == NULL)
{
puts("Could not open files");
exit(0);
}
while ((ch = fgetc(pointer1)) != EOF)
fputc(ch, pointer3);
while ((ch = fgetc(pointer2)) != EOF)
fputc(ch, pointer3);
printf("Merged file1.txt and file2.txt into combined.txt");
fclose(pointer1);
fclose(pointer2);
fclose(pointer3);
return 0;
}
Is there a way to output the described situation? I am aware that E0F refers to the end of a file, and is likely causing an issue. Is there a similar condition for an end of a line (like E0L)?
Edit: Changed char ch to int ch.
First, if you have a Unix-like system, the paste command already does that. Next as you want to process lines, you should use fgets. Here you have to loop over input files one line at a time, copy the lines to the output file without the newline, and add the new line after copying everything.
As the processing for both input files is the same, and as I am lazy, I wrote a function to only write it once. In the end code could be:
FILE *copyline(FILE *in, FILE *out) {
char line[256];
if (in != NULL) {
for (;;) { // loop if the line is larger that sizeof(line)
if (NULL == fgets(line, sizeof(line), in)) { // EOF on file1
fclose(in);
in = NULL;
break;
}
size_t end = strcspn(line, "\n");
if (end != 0) fwrite(line, 1, end, out); // smth to write
if (end != strlen(line)) break; // \n found: exit loop
}
}
return in;
}
int main()
{
FILE *pointer1 = fopen("file1.txt", "r");
FILE *pointer2 = fopen("file2.txt", "r");
FILE *pointer3 = fopen("combined.txt", "w");
const char sep[] = " "; // a separator between lines of both file
if (pointer1 == NULL || pointer2 == NULL || pointer3 == NULL)
{
puts("Could not open files");
exit(0);
}
for (;;) {
pointer1 = copyline(pointer1, pointer3);
fwrite(sep, strlen(sep), 1, pointer3);
pointer2 = copyline(pointer2, pointer3);
if (pointer1 == NULL && pointer2 == NULL) break;
fputc('\n', pointer3); // if smth was written, add a newline
printf(".");
}
printf("Merged file1.txt and file2.txt into combined.txt");
fclose(pointer3);
return 0;
}
Here's one way to approach it:
#include <err.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ) {
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
int
main(int argc, char **argv)
{
if( argc < 3 ) {
printf("usage: %s file1 file2\n", basename(argv[0]));
}
FILE *pointer1 = xfopen(argv[1], "r");
FILE *pointer2 = xfopen(argv[2], "r");
FILE *current = pointer1;
int ch;
while( ( ch = fgetc(current)) != EOF ) {
if( ch == '\n' ) {
if( current == pointer1 ) {
int k;
current = pointer2;
if( (k = fgetc(current)) != EOF ) {
ungetc(k, current);
ch = ' ';
}
} else {
current = pointer1;
}
}
putchar(ch);
}
if( ferror(current) ) {
err(EXIT_FAILURE, "Error reading %s",
current == pointer1 ? argv[1] : argv[2]);
}
current = current == pointer1 ? pointer2 : pointer1;
while( (ch = fgetc(current)) != EOF) {
putchar(ch);
}
fclose(pointer1);
fclose(pointer2);
return 0;
}
#include <stdio.h>
int main()
{
FILE *pointer1 = fopen("file1.txt", "r");
FILE *pointer2 = fopen("file2.txt", "r");
FILE *pointer3 = fopen("combined.txt", "w");
char ch1, ch2;
if (pointer1 == NULL || pointer2 == NULL || pointer3 == NULL)
{
puts("Could not open files");
return 0;
}
do
{
char c1 = fgetc(pointer1);
char c2 = fgetc(pointer2);
if (feof(pointer1) || feof(pointer2))
break;
while(c1!='\n')
{
fputc(c1,pointer3);
c1=fgetc(pointer1);
if(feof(pointer1)) break;
}
fputc(' ',pointer3);
while(c2!='\n')
{
fputc(c2,pointer3);
c2=fgetc(pointer2);
if(feof(pointer2)) break;
}
fputc('\n',pointer3);
} while (1);
printf("Merged file1.txt and file2.txt into combined.txt");
fclose(pointer1);
fclose(pointer2);
fclose(pointer3);
return 0;
}
This works like you want.
Output: Combined file.txt
file1-line1 file2-line1
file1-line2 file2-line2
file1-line3 file2-line3
So i have to write a function that reads a file (.txt) and searches for a specific string, and then make it return the whole line that the string was on.
For example, one line is composed by student number, name, date of birth, address and course. I need to search for a name, and i need it to return the whole line, containing number, name, etc.
Ex :
Input : Search for student name : HUGO
Output :
61892 HUGOABC 12-02-2001 Address123 ETD
81029 HUGOBCA 09-09-2000 Address123 EAC
Here's my code :
fp = fopen("database_Alunos.txt", "r+");
if (fp == NULL) {
printf("Error! File is NULL...");
system("pause");
main();
}
else {
char nome[50];
printf("Choose name to search : ");
scanf("%[^\n]s", &nome);
/* ??? */
fclose(fp);
system("pause");
main();
fp is a FILE *fp, declared on top of main();
I need to know what kind of functions I can use in the space in the code with the question marks to make it scan for 'nome' and return the whole line
You'll need to loop through a getline using your fp, then you can use for example strstr to check if the name is present in this string. Note that you'll have to handle the case when the name is present in the address.
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, fp)) != -1) {
if (strstr(line, nome) != NULL) {
printf("%s\n", line);
}
}
Ok i figured it out, this is a function to read the line
int readline(char *buff, int len, FILE *fp) {
buff[0] = '\0';
buff[len - 1] = '\0';
char *tmp;
if (fgets(buff, len, fp) == NULL) {
*buff = '\0';
return 0;
}
else {
if ((tmp = strrchr(buff, '\n')) != NULL) {
*tmp = '\0';
}
}
return 1;
}
Func to read name and return lines :
scanf("%[^\n]s", fgets(nome, sizeof(nome), stdin));
char line[1024];
while (readline(line, 1024, fp)) {
char *aux = strdup(line);
char *numero = strtok(aux, "\t");
char *nomeAluno = strtok(NULL, "\t");
if (strstr(nomeAluno, nome) != NULL) {
printf("%s\n", line);
}
}
}
The programm should be able to open a file like myFile.txt,
alltough it's real name is myFile without the extension .txt.
So I wrote the function called removeFileExtension() in order
to achieve that.
It does open my file by copying the string from text into filename:
strcpy(filename,text);
FILE *fp = fopen(filename, "r");
So I tried to check what the difference between text and my processed
string from removeFileExtension is.
To check if it even works I mate a function called strComparison(),
which returns either 0 when it is qual or 1 if unequal.
The thing is, after removing the file extension, it shows that both strings
are qual, but I am still not able to open the file.
When I type in ./a.out myFile.txt my comparison function returns 0,
it is equal, but fopen() still is not able to open the file,
respectively I allways get a Segmentation fault.
Does anyone see the problem here?
Why am I getting a Segmentation fault?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void removeFileExtension(char *haystack);
int strComparison(char *one, char *two);
int main(int argc, char const *argv[])
{
//----------------------------------------------------------------------------
// CHECK INPUT VALIDITY
//
if (argc != 2)
{
printf("Usage: ./ass2 [file-name]\n");
return 1;
}
//----------------------------------------------------------------------------
// OPEN FILE (INITIAL)
//
char filename[32];
strcpy(filename, argv[1]);
FILE *fp = fopen(filename, "r"); //FOPEN
//FILE *fp = fopen("start_of_story\0txt", "r"); // this way does work
if (fp == NULL)
{
// IF NOT FOUND: REMOVE EXTENSION
removeFileExtension(filename);
char text[] = "myFile\0";
int ret_val = -1;
ret_val = strComparison(filename, text);
if (ret_val == 0)
printf("[DEBUG] equal\n");
else
printf("[DEBUG] unequal\n");
printf("[DEBUG] ret_val: %d\n", ret_val);
printf("[DEBUG] '%s'\n", filename);
FILE *fp = fopen(filename, "r"); //FOPEN
// IF STILL DOESN'T WORK: ERROR
if (fp == NULL)
{
printf("[ERR] Could not read file %s.\n", filename);
return 3;
}
}
//--------------------------------------------------------------------------
// READ DATA (INITIAL)
//
int bufsize = 1024;
char *buffer = malloc(bufsize * sizeof(char)); //MALLOC
if (!buffer)
{
printf("[ERR] Out of memory.\n");
return 2;
}
fseek(fp, 0, SEEK_SET);
fread(buffer, bufsize, 1, fp);
printf("[DEBUG] %s\n", buffer);
fclose(fp); //FCLOSE
free(buffer);
buffer = NULL;
return 0;
}
void removeFileExtension(char *haystack)
{
char needle[1] = ".";
char *retp; // return pointer
retp = strstr(haystack,needle);
if (*retp == '.')
{
while (*retp != '\0')
{
*retp++ = '\0';
}
printf("[DEBUG] %s\n", haystack);
}
}
int strComparison(char *one, char *two)
{
do
{
printf("[DEBUG] '%c' == '%c'\n", *one, *two);
if (*one++ != *two++)
{
return 1; // return 1 if unqual
}
}
while ( (*one != '\0') || (*two != '\0') );
return 0; // return 0 if qual
}
Resulting output:
user#host ~/Desktop $ ./a.out myFile.txt
[DEBUG] myFile
[DEBUG] 'm' == 'm'
[DEBUG] 'y' == 'y'
[DEBUG] 'F' == 'F'
[DEBUG] 'i' == 'i'
[DEBUG] 'l' == 'l'
[DEBUG] 'e' == 'e'
[DEBUG] equal
[DEBUG] ret_val: 0
[DEBUG] 'myFile'
[ERR] Could not read file myFile.
user#host ~/Desktop $
Quoting C11, chapter 7.24.5.7
char *strstr(const char *s1, const char *s2);
The strstr function locates the first occurrence in the string pointed to by s1 of the
sequence of characters (excluding the terminating null character) in the string pointed to
by s2.
So, both the arguments passed to strstr has to be strings. In your case,
char needle[1] = ".";
is not a string. You did not allow the space for the null-terminator. Either use
char needle[2] = ".";, at least, or,
char needle[ ] = ".";, or,
char const* needle = ".";
As a side effect, whenever the call to removeFileExtension() is reached, you'll face with undefined behavior
That said, beware!!
You are doing something like
retp = strstr(haystack,needle);
if (*retp == '.')
i.e., dereferencing the returned pointer from strstr(). If, strstr() returns a NULL pointer, you'll again be trapped in UB.
EDIT:
For those who still has confusion about string, check definition in chapter ยง7.1.1 (emphasis mine)
A string is a contiguous sequence of characters terminated by and including the first null
character. [...]
At least I found the problem:
After removing the file's extension, I am still
trying to open the old file pointer fp, which
gave me the NULL-pointer back. The new file pointer
inside the body of the if(fp == NULL){...} only
exists inside the scope of the if-statement.
So I created a test_pointer, which first looks if
the file even exists, if not, he removes the extension.
Than I try again to open the file, this time with fp.
Thanks to everybody for the hints, especially to
Sourav Ghosh
for your improvement suggestions!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int removeFileExtension(char *haystack);
int main(int argc, char const *argv[])
{
char filename[64];
strcpy(filename, argv[1]);
//----------------------------------------------------------------------------
// CHECK INPUT VALIDITY
//
if (argc != 2)
{
printf("Usage: ./ass2 [file-name]\n");
return 1;
}
//----------------------------------------------------------------------------
// CHECK FILE EXISTENSE
//
FILE *test_pointer = fopen(filename, "r"); //FOPEN
if (test_pointer == NULL) // if not found: remove extension
{
int ret_val = removeFileExtension(filename);
if (ret_val == -1)
{
printf("[ERR] Could not remove file extension.\n");
return 3;
}
}
//----------------------------------------------------------------------------
// OPEN FILE (INITIAL)
//
FILE *fp = fopen(filename, "r"); //FOPEN
if (fp == NULL) // if still doesn't work: error
{
printf("[ERR] Could not read file %s.\n", filename);
return 3;
}
//----------------------------------------------------------------------------
// READ DATA (INITIAL)
//
int bufsize = 1024;
char *buffer = malloc(bufsize * sizeof(char)); //MALLOC
if (!buffer)
{
printf("[ERR] Out of memory.\n");
return 2;
}
fseek(fp, 0, SEEK_SET);
fread(buffer, bufsize, 1, fp);
fclose(fp); //FCLOSE
printf("[DEBUG] %s\n", buffer);
free(buffer); //FREE
buffer = NULL;
return 0;
}
int removeFileExtension(char *haystack)
{
char needle[] = ".";
char *retp; // return pointer
retp = strstr(haystack,needle);
if(!retp) // to prevent UB
return -1;
if (*retp == '.')
{
while (*retp != '\0')
{
*retp++ = '\0';
}
printf("[DEBUG] %s\n", haystack);
}
return 0;
}
Hi all I'm trying to write a function that returns the line of data and returns it in a String. Below is my code and I'm not sure why it's not working. I've added in a printf function and when I call the function nothing prints out.?
EDIT (cause i can't answer yet) - Thanks for your replies. When I change char c to char *c it still doesn't work. I just need to read the line into a string and return it.
char* getLine(FILE *file, int lineNum){
char c;
int lineCount=0, size = 1;
char *line = NULL;
line = malloc(sizeof(char)*size);
while ((c=getc(file)) != EOF){
if (c=='\n'){
++lineCount;
continue;
}
if (lineCount==lineNum){
size += 1;
line = realloc(line, size*sizeof(char));
strcat(line, c);
printf("Line: %s\n", line);
}
}
return line;
}
Variable c is not of type const char *
See strcat documentation
It's not very efficient, but it should do what you want:
Note that lineCount starts at 0. (The first line is line 0).
char* getLine(FILE *file, int lineNum){
char c;
int lineCount=0, size = 0; // start size at zero, not one
char *line = NULL;
while ((c=getc(file)) != EOF){
if (lineCount==lineNum){
size += 1;
if(line == NULL) {
line = calloc(sizeof(char), size);
} else {
line = realloc(line, size*sizeof(char));
}
char ac[2] = { c, 0 }; // this line is new
strcat(line, ac); // ac is new here
printf("Line: %s\n", line);
if(c == '\n') {
return line;
}
}
if (c=='\n'){
++lineCount;
}
}
printf("Could not find line %d\n", lineNum);
return NULL;
}