I've started to write a program that reads and stores team info and stores in a structure, reorders and prints results.
First i'm trying to read team names and stores them in a member in a structure, then read team scores and store them in another member.
However, as soon as i debug the file, it crashes. It doesn't even start correctly. I get this error
Unhandled exception at 0xFEFEFEFE in PA2.exe: 0xC0000005 Access
violation executing location 0xFEFEFEFE.
I've backtracked enough to figure out that it is somewhere in the while loop but can't figure out what's wrong with it.
I am using visual studio 2012 and i get no errors when i build it.
#include "stdafx.h"
#include "string.h"
#include <stdio.h>
struct team
{
char name[20];
int no_games;
int points;
int goals_scored;
int goals_let;
};
int main(void)
{
FILE *input2a;
FILE *input2b;
int error1;
int error2;
int i;
char team1_name[20];
char team2_name[20];
int team1_goals;
int team2_goals;
struct team teamlist[20];
error1 = fopen_s(&input2a, "C:\\Users\\New PC\\Desktop\\input2a.dat", "r");
i = 0;
while (i < 20)
{
i ++;
fscanf_s(input2a, "%s", teamlist[i].name);
}
error2 = fopen_s(&input2b, "C:\\Users\\New PC\\Desktop\\input2b.dat", "r");
while (fscanf_s(input2b, "%s %d %s %d", team1_name, &team1_goals, team2_name, &team2_goals) !=EOF)
{
if (team1_goals < 0)
{
printf("Team %s has negative goals - Invalid entry\n", team1_name);
}
else if (team2_goals < 0)
{
printf("Team %s has negative goals - Invalid entry\n", team2_name);
}
else
{
}
}
return 0;
}
From only looking at the while loop: you write to memory out of bounds.
struct team teamlist[20];
And in the while:
i = 0;
while (i < 20)
{
i ++;
fscanf_s(input2a, "%s", teamlist[i].name);
}
So you enter the while when i=19 and increase it to 20 which makes it out of the bounds for the array.
The problem is here (see my comment):
i = 0;
while (i < 20)
{
i ++; // was 19, become 20, but maximal allowed value is 19
fscanf_s(input2a, "%s", teamlist[i].name);
}
The name of this problem is ABW (array bounds write). It means, that your program writes outside array (it happens when i==19, so the condition of the loop i < 20 is satisfied, but right after it you increase it: i++). To fix it you need just to swap two lines of the body of this loop:
{
fscanf_s(input2a, "%s", teamlist[i].name);
i++;
}
And much better and simplier it would be to use for loop here:
for (i = 0; i < 20; i++)
fscanf_s(input2a, "%s", teamlist[i].name);
And the last fix: now there is still possible ABW error. The reason of it is simple: size of teamlist[i].name is 20. So, if input file contains long lines, your program will write outside this array. To fix it you can extend "%s this way (we have here "19" instead of "20" because last character is '\0'):
for (i = 0; i < 20; i++)
fscanf_s(input2a, "%19s", teamlist[i].name);
And one more thing about fscanf_s(): this function shall return the number of successfully matched and assigned input items. So in the second loop it is better to check, that it returns 4.
Update:
If nothing happens, let's open documentation:
Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size
to be specified for all input parameters of type c, C, s, S, or string
control sets that are enclosed in []. The buffer size in characters is
passed as an additional parameter immediately following the pointer to
the buffer or variable. For example, if you are reading a string, the
buffer size for that string is passed as follows:
char s[10];
scanf_s("%9s", s, _countof(s)); // buffer size is 10, width specification is 9
So in your case in means, that first loop should be corrected this way:
for (i = 0; i < 20; i++)
fscanf_s(input2a, "%19s", teamlist[i].name, _countof(teamlist[i].name));
And you need the same fix for next call of fscanf_s in the second loop, because there are two "%s"s in that call.
Related
I have been writing a program to input a phrase and turn it into an acronym. For some reason when I output my acronym at the moment it comes out with a bunch of random characters. How do I fix it?
#include <stdio.h>
#include <string.h>
#define MAXLEN 50
int main() {
int num;
printf("Enter number of acronyms to add to the database:");
scanf("%d", &num);
getchar();
char strings[num][MAXLEN];
char acronym[num][MAXLEN];
for(int i = 0; i < num; i++){
printf("Enter the string to convert into an acronym:");
fgets(strings[i],MAXLEN,stdin);
printf("%s\n", strings[i]);
for(int j = 0; j < 11; j++){
if((strings[i][j]) >= 'A' && (strings[i][j]) <= 'Z'){
char buffer[][20] = {strings[i][j]};
strcat(acronym[i], buffer[i]);
}
}
puts(acronym[i]);
}
return 0;
}
I have tried changing the MAXLEN value to see if it was a memory issue or like a buffer overload. I've also just tried changing around how the strings switch and work together but nothing has worked.
char buffer[][20] = {strings[i][j]};
Here you let the compiler count how many elements the array has from the initialization.
It has 1 element, A string with single a single character strings[i][j] and rest of the 20 byte array filled with 0.
strcat(acronym[i], buffer[i]);
Here you access buffer[i], but there is only one string there (as explained above), so this is invalid if i is anything but 0.
I'm not sure what you are trying to do, but this would be valid implementation of what this code tries to do:
// extract single character as a string
char buffer[2] = {strings[i][j], 0}; // only one of 2 and 0 is mandatory
// append it to acronym
strncat(acronym[i], 20, buffer);
Probably lots of other stuff there is wrong, but here is one definite issue and a possible solution.
I'm not sure why I'm receiving this error. I was wondering could it be due to my terminal not being able to read the txt files that run with this program. Let me know if that could be a possible reason for that message.
Im mainly just looking for syntax errors. The files I have just contain a big bunch of numbers and I'm supposed to work from the third value onwards {the first two have another use)
#include <stdlib.h>
#define N 1000000
int main(void)
{
int n; /* The number of lengths */
int x; /* The target length */
int lengths[N]; /* The array of available lengths */
int i, j;
int whichfile=1;
FILE *fp;
scanf("%d", &whichfile);
switch (whichfile) {
case 1:
fp = fopen("testcase_small_sorted.txt", "r");
break;
case 2:
fp = fopen("testcase_large_sorted.txt", "r");
break;
case 3:
fp = fopen("testcase_small_nomatch_sorted.txt","r");
break;
case 4:
fp = fopen("hidden_small_sorted.txt","r");
break;
case 5:
fp = fopen("hidden_large_sorted.txt","r");
break;
}
fscanf(fp, "%d", &x);
fscanf(fp, "%d", &n);
for (i=0;i<n;i++)
fscanf(fp, "%d", &lengths[i]);
fclose(fp);
/* Now all the input data has been read in
search for the required pair of lengths... */
x = lengths[0];
n = lengths[1];
for(i = 2; i < n; i++)
{
for(j = 2; i < n; j++)
{
if(lengths[i] + lengths[j] == x)
{
printf("Found: %d + %d == %d\n", lengths[i], lengths[j], x);
}
}
}
return 0;
} ```
I'm mainly just looking for syntax errors.
Syntax errors are only the beginning. C will not check anything for you. You have to check if files opened, if input scans worked, if values are inside array bounds. If you don't, that's how you get segfaults.
For files, the usual pattern is to try to open the file, check its return value, and then handle the error. fopen returns NULL on error and sets errno. errno is a global which holds what sort of error happened like "file not found", but it's a number. strerror is handy to turn it into an error message. Finally fprintf is like printf but can print to things other than stdout. In this case stderr. Both stdout and stderr normally appear on the screen, but they can be separated.
FILE *fp = fopen(path, mode);
if( fp == NULL ) {
// This will print something like "Could not open testcase_small_sorted.txt: No such file or directory"
fprintf(stderr, "Could not open file %s: %s", path, strerror(errno));
exit(1);
}
But now we need to copy this five times because the code repeats fopen. Instead of each case opening the file, what if it just picked a filename? And since each filename has a number, what if they were just in an array?
const char *files[] = {
NULL, // 0 is not used
"testcase_small_sorted.txt",
"testcase_large_sorted.txt",
"testcase_small_nomatch_sorted.txt",
"hidden_small_sorted.txt",
"hidden_large_sorted.txt"
};
const char *path = files[whichfile];
What if they input something that's not a number? Or what if the number is out of range? These need to be checked for as well. scanf will return the number of items matched. We expect 1. If we get anything else it didn't work.
// Check that we read an integer.
if( scanf("%d", &whichfile) != 1 ) {
fprintf(stderr, "Please enter 1-5.\n");
exit(1);
}
// Check that it's in range.
if( (whichfile < 1) || (5 < whichfile) ) {
fprintf(stderr, "Please enter 1-5.\n");
exit(1);
}
Note that scanf has a lot of problems and should be swiftly discarded once you learn things like fgets and sscanf.
int lengths[1000000] is 4 to 8 megabytes (1 million integers at 4 or likely 8 bytes per integer) and might get you an eponymous stack overflow. Your algorithm is O(n^2) which means if there really were 1,000,000 items it would take 1,000,000,000,000 iterations to find all the pairings and your class will probably be done before the program is.
(A little hint to improve the algorithm: if the numbers are sorted, and you're looking for two of them to sum X, do you need to check every number?)
I think you're meant trust n from the file for how many to read. Normally you don't have this, it's a crutch to let you read input without using dynamic memory (you'll be taught that later). Even if you had it, you wouldn't trust it anyway in production code; if it lies you'll walk out of your array bounds. But for this exercise that's fine.
// Read the first two lines, the sum and the number of remaining lines.
// Note that `fscanf` can also fail and needs to be error checked.
// I'll leave that as an exercise.
fscanf(fp, "%d", &x);
fscanf(fp, "%d", &n);
// Use `n` to allocate just enough space on the stack.
int lengths[n];
// Read the rest.
// Use braces, even for one line.
// They avoid a very silly and hard to debug mistake.
for (i=0;i<n;i++) {
fscanf(fp, "%d", &lengths[i]);
}
fclose(fp);
There's no need to put x and n into lengths. They aren't meant to be summed and you skip over them anyway by starting your loops at 2.
With that fixed the loops can start at 0. There is a mistake in the inner loop, it should check j < n not i < n.
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++) // <<--- j < n, not i < n.
{
if(lengths[i] + lengths[j] == x)
{
printf("Found: %d + %d == %d\n", lengths[i], lengths[j], x);
}
}
}
I'm trying to write a program to take 10 words as input from the user, then store it an array, and then print out the length of each word.
Here's my code:
#include <stdio.h>
#include <string.h>
char *words[10];
char length[10];
int i, j;
int main()
{
printf("Input ten words: \n");
for(i = 0; i < 10; i++)
{
printf("Enter element %d \n", i + 1);
scanf("%s", &words[i]);
}
for(i = 0; i < 10; i++)
printf("%c", words[i]);
for(i = j = 0; j < 10; j++)
{
length[j] = strlen(words[i]);
i++;
}
for(j = 0; j < 10; j++)
printf("%c", length[j]);
return 0;
}
It should be noted that I have no idea why the array "words" is defined as a pointer, I only do it because if I don't I get some warning about making a pointer from integer without a cast.
When I run the program what happens is, I get prompted to input the 10 elements, that much works, but then when it's supposed to print the "words" array, the program just crashes.
Also the reason I coded it like this is because later on I also need to print the longest and shortest word - so I figured it would help if I had the lengths of all the strings in their own array.
Does anyone know what's wrong here?
Thanks
With the line char *words[10], you are declaring an array of 10 pointers. However, these pointers are uninitialized, which means they are wild pointers. Dereferencing a wild pointer causes undefined behavior (i.e. the program may crash). If you want to use these pointers in a meaningful way, you must make each pointer point to a valid memory location, for example to an address returned by the function malloc or to the address of a char array.
However, probably the easiest solution to your problem is to not use pointers at all, but to instead declare a two-dimensional char array, like this:
char words[10][100];
That way, you are allocating space for 10 words of up to 100 characters each (including the null terminating character).
Beware that a buffer overflow will occur if the user enters a word longer than 99 (1 byte is required for the terminating null character). Therefore, the scanf line should be changed to the following:
scanf("%99s", words[i]);
That way, scanf will never attempt to write more than 100 bytes (including the terminating null character).
I have also removed the & in the scanf line above, because the & is not necessary, since words[i] will automatically decay to &words[i][0].
Also, as a general rule, you should verify that the return value of scanf is 1 before attempting to use the value that scanf wrote. For example, if the user triggers end of file on the input stream (for example by pressing CTRL-D on Linux or CTRL-Z on Windows), then scanf will return -1 without writing anything into words[i]. In that case, by subsequently reading from words[i], your program will cause undefined behavior.
Additionally, the line
printf("%c", words[i]);
must be changed to:
printf("%s", words[i]);
The loop
for(i = j = 0; j < 10; j++)
{
length[j] = strlen(words[i]);
i++;
}
can be simplified to:
for(i = 0; i < 10; i++)
{
length[i] = strlen(words[i]);
}
The line
printf("%c", length[j]);
should probably be changed to
printf("%hhu", length[j]);
because length[j] does not represent the ASCII code of a character, but just a number.
I'm quite new to C and I was wondering if it is possible to have a variable be defined by an input by the user. I've made a simple prime number counter which shows all the prime numbers from 1 to 100 and I was wondering if there is a library or a code which allows me to define a variable by the user input. Here's my code for better understanding.
#include <stdio.h>
int main(void)
{
for (int i = 2; i < 101; i++) { //I would want the "101" to be a user defined variable
for (int j = 2; j <= i; j++) {
if (i == j) {
printf("%d\n", i);
}
else if (i%j == 0) {
break;
}
}
}
}
Thanks in advance!
#include <stdio.h>
int main(void) {
int num;
scanf("%d",&num); //to take a user input
for (int i=2; i<=num; i++) //I would want the "101" to be a user defined variable
{
for (int j=2; j<=i; j++)
{
if (i == j)
printf("%d\n",i);
else if (i%j == 0)
break;
}
}
}
Yes, using user input in this way is possible. (It had better be possible! Virtually all programs work on user input.)
In general, there are two main ways of doing it. (1) read from the command line. (2) read from a "file" -- which might just be the user's keyboard.
Let's look at both of these in turn.
1. Read from the command line.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int max;
if(argc <= 1)
{
fprintf(stderr, "usage: %s max\n", argv[0]);
exit(1);
}
max = atoi(argv[1]);
for (int i=2; i<max; i++)
{
for (int j=2; j<=i; j++)
{
if (i == j)
printf("%d\n",i);
else if (i%j == 0)
break;
}
}
}
To read from the command line, we declare main with two arguments: argc and argv. When main gets called, argc will be a count of how many arguments there are, and argv will contain those arguments. argv is an array of strings, or more precisely, an array of pointers to char, or char *. Also, the first argument will always be the name of the program.
We want the user to type
name_of_the_program 200
to print primes up to 200. So we make sure that the user typed at least one argument, that is, we complain if argc isn't at leaast 2: one for the name of the program, 1 for the argument the user typed. Assuming the user did type an argument, it'll be in argv[1]. (argc[0] is the program name.) The command-line arguments are always passed as strings, but we want a number, an int. So we call atoi to convert the string on the command line (like "200") to an int (like 200).
2. Read from a file.
In this case, the "file" we're going to read from is stdin, the standard input, which by default is the user's keyboard.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int max;
char input_line[100];
printf("How high to go? "); fflush(stdout);
fgets(input_line, 100, stdin);
max = atoi(input_line);
if(max == 0)
{
fprintf(stderr, "try typing a number next time\n");
exit(1);
}
for (int i=2; i<max; i++)
...
We print a prompt to tell the user what we need him to type. We call
fgets(input_line, 100, stdin);
to read one line of input -- that is, we expect the user to type some stuff, then hit RETURN. Since we declared input_line to be an array of 100 characters, it's important that we tell fgets how big it is, so that fgets can be sure not to put more than 100 characters into the array. (That could happen if the user, just to be ornery, typed 100 or more characters before hitting RETURN.)
Similarly to the command line case, we've read input_line as a line of text, a string. So we call atoi again, to convert that string to an int. Also, we make sure that the number is not 0. If the user types "abc" or something, that isn't even a number, atoi will return 0, and we catch that, since we'd never want to try to print prime numbers up to 0.
[P.S. As an alternative to the fgets plus atoi technique I've presented here, another popular method is the scanf function (as illustrated, in fact, in another answer to this question). You can use scanf, and it even seems pretty easy at first, but in the long run it's harder, and there are a bunch of things it doesn't handle at all well. So I recommend learning how to use fgets and friends as soon as you can.]
I'm fairly new to coding and am currently taking a programming course at school with C. We were given an assignment and I'm having a bit of difficulty with the first part. We're learning how to use the string-handling library (stdlib.h) and the objective of the assignment is to input multiple lines of text from the keyboard. The instructor advised us to use two-dimensional arrays in order to do this, but I'm a bit stuck. Here's the code I've written:
int main(void) {
char string[3][SIZE];
int i, j;
int c;
printf("Enter three lines of text:\n");
for (i = 0; i < 3; i++) {
j = 0;
while ((j < SIZE) && (c = getchar() != '\n')) {
string[i][j] = c;
j++;
}
}
for (i = 0; i < 3; i++) {
for (j = 0; j < SIZE; j++) {
printf("%c", string[i][j]);
}
printf("\n");
}
return 0;
}
Some points that I'd like to make are that I used the getchar() function to receive input one character at a time, and also the second for loop I intended to print each line of text that is stored in each row of the string array.
The input is any string of text for three lines, for example:
Hi my name is John.\n
I am from the US\n
and I'm a student.
Here's what the current output looks like:
Enter three lines of text:
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr...
The output that I'm expecting is:
Enter three lines of text:\n
Hi my name is John.\n
I'm from the US\n
and am a student.
Any tips or advice would be greatly appreciated. Thank you!
First of all let me commend the fact the you starting your way with C. That's the most solid language to learn(better is only assembly itself) - you will have a full understanding of how things work, which you wouldn't get if started from some language written on top of C(like Java and Python).
But it's a hard and long road, which worth that.
On the code: there is a lot going and you have made a lot of amusing bugs that would reproduce different interesting things every other time and machine you run it.
First of all: to make your code work somehow all you need is add parenthesis:
while ((j < SIZE) && ((c = getchar()) != '\n')) {
In C everything is binary(or integer, depending how you look at it) and default binding is to the right a op1 b op2 c op3 d..
First op3 is evaluated c op3 d = r1, then you have a op1 b op2 r1 and so on.
Thus you was comparing the value of getchar() with value of character '\n' - which are not equal, so you get TRUE (value 1) and store it in local variable c.
Next you still have some problems because of the way you initialized your array:
char string[3][SIZE];
What it does is simply "intrusts" 3*SIZE*sizeof(char) bytes of you process address space to a thing labeled "string". But that does not clear up all the remnants of previous live (of your program, or even before) on those bytes, so if it happens that SIZE in your program == 100 and you used to store your credit card on a real address memory (RAM) mapped to that region of your program memory you would see your credit card when you print it by printf - if you didn't overwrite those 300 bytes.
This may help you looking at it:
#include <stdlib.h>
#include <stdio.h>
#define SIZE 10
int main(void) {
char string[3][SIZE];
int i, j;
int c;
for(i = 0; i < 3; i++)
for(j = 0; j < SIZE; j++){
string[i][j] = 0;
}
printf("Enter three lines of text:\n");
for (i = 0; i < 3; i++) {
j = 0;
while ((j < SIZE) && ((c = getchar()) != '\n')) {
string[i][j] = c;
j++;
}
}
for (i = 0; i < 3; i++) {
for (j = 0; j < SIZE; j++) {
printf("%c", string[i][j]);
}
printf("\n");
}
return 0;
}
Also be aware that getchar() may behave lousy with input and newlines - it depends on whether you console buffers input before sending it to your program on enter(newline) or not. More here How to avoid press enter with any getchar()
Note: I wrote this answer before the OP clarified they had to use getchar.
To read a whole line at a time, use fgets. To print a whole string at a time, use printf with the %s format.
#include <stdio.h>
int main(void) {
// No need to define a SIZE constant.
// Because it's stack allocated we can its size.
char strings[3][100];
printf("Enter three lines of text:\n");
for ( int i = 0; i < 3; i++) {
// Reads one line, up to the size of `strings[i]`, from stdin.
fgets( strings[i], sizeof(strings[i]), stdin );
}
for ( int i = 0; i < 3; i++) {
// Print each string and its line number.
printf("Line %d: %s\n", i, strings[i]);
}
return 0;
}
This is not the best pattern to read input. You'll learn very quickly that fixed memory sizes and reading input don't work well. For future reference, it would be more like this.
#include <stdio.h>
#include <string.h>
int main(void) {
// A list to store 3 strings, but no memory for the strings themselves.
char *strings[3];
printf("Enter three lines of text:\n");
// A line buffer that's sufficiently large.
// This will be reused.
char line[4096];
for ( int i = 0; i < 3; i++) {
// Read into the large line buffer.
fgets( line, sizeof(line), stdin );
// Copy the string into a buffer that's just big enough.
strings[i] = strdup( line );
}
for ( int i = 0; i < 3; i++) {
printf("Line %d: %s\n", i, strings[i]);
}
return 0;
}
This allocates a single large line buffer to do the reading, then copies what its read with strdup to memory of just the right size. This lets you read even very long lines of input without wasting a bunch of memory if they're very short.
Note that strdup() is not part of the C standard library, but it's part of the POSIX spec. Any major compiler will have it, and it's easy to write your own.