I have come across the following problem.
I have a program which allows the user to create a .txt file and add up to 10 ASCII values.
I am then closing the file, and re-opening in read mode. The point of this being that I am converting the inputted ASCII to integer using ATOI.
The working code for this is provided below.
My problem is: I want to create some sort of array which stores these inputted ASCII values. BY doing so, this will enable me to call upon a function to check which of these ASCII values is smallest.
fp = fopen("c:\\CTEMP\\1.txt", "w+");
{
for (x = 0; x < 10; x++)
{
printf("\nType the word you want to add. Type exit to terminate: ");
scanf("%s", word); // word is declared as char word[10]
if (strcmp(word, "exit") == 0)
{
break;
}
fprintf(fp, "%s\n", word);
words++;
}
fclose(fp);
}
fp = fopen("C:\\CTEMP\\1.txt", "r");
while (!feof(fp))
{
fscanf(fp, "%s", &word);
number = atoi(word);
printf("\nstring is \t %s\n", word);
printf("integer is \t %d\n", number);
// location = find_minimum(array,number);
// minimum = array[location];
// printf("Minimum element location = %d and value = %d.\n", location + 1, minimum);
}
scanf_s("%d");
}
Am I tackling the problem of finding the smallest ASCII value correctly?
Is there any other way without creating another array to store the ASCII values?
As mentioned by Barmar, there is no need to store all the values in an array just for the sake of finding the minimum then. Let a variable minNr store the smallest number read so far, and let minIdx store it's index. Whenever the number read in the current pass is smaller (or equal) then minNr, adapt minNr and minIdx accordingly. Thereby, for any two equal numbers read in, the latter will be considered as the minimum's index. Note that minNr is initialized with INT_MAX, such that already the very first number read in will "beat" this initial value:
int finished = 0;
int minNr = INT_MAX;
int minIdx = 0;
fp = fopen("C:\\CTEMP\\1.txt", "r");
if (fp==NULL)
finished=1;
for (int i=1; !finished; i++)
{
char word[50];
if (fscanf(fp, "%s", word) < 1)
finished = 1;
else {
int number = atoi(word);
printf("\nstring is \t %s\n", word);
printf("integer is \t %d\n", number);
if (number <= minNr) {
minNr = number;
minIdx = i;
}
}
}
if (minIdx > 0)
printf ("min number is %d at position %d\n", minNr, minIdx);
else
printf("no numbers read in; hence: no minimum calculated.");
BTW: in your code, if word is declared as something like char word[50], then statement fscanf(fp, "%s", &word) should give you at least a compiler warning because of the superfluous &.
My problem is: I want to create some sort of array which stores these
inputted ASCII values. BY doing so, this will enable me to call upon a
function to check which of these ASCII values is smallest.
I don't know what an ASCII value is but here's how you:
char chars[10]; //create an array of 10 characters
int ints[10]; //create an array of 10 ints
char strings[10][10]; //create an array of 10 9-character strings
Am I tackling the problem of finding the smallest ASCII value correctly?
Semantically, perhaps. But you're 1) being spacially inefficient by trying to store all the elements (you probably don't need to store them -- not in memory, not on disk) and 2) you're failing to do error handling on the IO functions you call. Additionally 3) you're creating a security hole with scanf("%s", without a length limit.
Is there any other way without creating another array to store the ASCII values?
Yes. Store only your current candidate for the minimum value. The rest can be forgotten.
Related
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 very new to programming and C. I have textfile with some random text and an integer that i want to find and save. The textfile looks something like this (I only want to save 23 in this case, not 56):
# this is a comment
23
this is some random text
56
And this is the code I have:
int *num = malloc(sizeof(int));
*num = fgetc(f);
while(!feof(f)){
*num = fgetc(f);
if(isdigit(*num)){
break;
}
}
if(!isdigit(*num)){
printf("Error: no number found.\n");
free(num);
}
else{
printf("%c\n", *num);
}
I'm kinda stuck right now and my program only prints out the number 2 :/
Very thankful for help.
As #pbn said you're better off using sscanf.
But if you really, really want, you can do it your way, by reading one character at a time, but you'll need to "build" the integer yourself, converting the character to integer, keeping track of what you have, and multiplying by powers of 10 for every digit the number that you already have.
Something like this (not complete code, it's just to get you started):
int c;
int num = 0;
while (c = fgetc(f)) {
if(!isdigit(c)) {
break;
}
num = (num * 10) + (c - '0');
}
The c- '0' part is to convert the text representation of the integer to the integer itself. 0 is character 48, 1 is 49 and so on.
This is assuming that on the line with numbers, you ONLY have numbers, not a mix of numerical and non-numerical characters.
Also, do not use !feof(file).
One option could be using getline and sscanf functions. I assumed that text lines do not contain numbers:
#include <stdio.h>
int main() {
int value, matched = 0;
char *line = NULL;
size_t size;
while(getline(&line, &size, stdin) != -1) {
if ((matched = sscanf(line, "%d", &value)) != 0)
break;
}
if (matched)
printf("value: %d\n", value);
return 0;
}
This part:
while(getline(&line, &size, stdin) != -1) {
will try to read the entire stream line by line.
Next line uses sscanf return value, which is the number of input items successfully matched and assigned, to determine whether the integer value has been found. If so it stops reading the stream.
One simple way in your program is once you find digit don't just stop continue untill you find next " " , "\n" , "\0" . Till then add Number = Number*10 +(*num);, define Number as global or something.
I found an answer to the first part of my question (how to read multiple values with scanf) but it doesn't seem to work for me (I think it's because of putting the values into an array and maybe also because I'm checking if the values given are 6 ints for sure):
I am writing a program that stores co-ordinates of 4 triangles in an array. Each line has 6 values and stores co-ordinates of one triangle. I want to read 6 co-ordinates at one time and do this operation for 4 triangles separately.
int tab[4][6];
for (int i = 0; i < 4; i++){
while (scanf("%d %d %d %d %d %d", &tab[i][0], &tab[i][1], &tab[i][2], &tab[i][3], &tab[i][4], &tab[i][5]) != 6){
printf("Error, try again: ");
while (getchar() != '\n'){}
}
}
So for example if first triangle's co-ordinates are (2,1), (5,6), (2,7), then I want to type in: "2 1 5 6 2 7" and as a result I want it to fill the first line of the array with the said numbers in the order I typed them in.
Obviously it doesn't work, the program stops working (not finishes the work, it stops) after the first line is given.
I get this error after debugging (after giving first line):
"Unhandled exception at 0x0FDCC28C (msvcr120d.dll) in xxx.exe: 0xC0000005: Access violation writing location 0xCCCCCCCC."
How to fix it?
You need to subtract the pointer i when detecting input error like this for example ->
#include <stdio.h>
int main(int argc, const char * argv[]) {
int tab[4][6];
for (int i = 0; i < 4; i++){
printf("Enter 6 values \n");
int retVal=scanf("%d %d %d %d %d %d", &tab[i][0], &tab[i][1], &tab[i][2], &tab[i][3], &tab[i][4], &tab[i][5]);
if (retVal == 6) {
printf("You did enter -> %d %d %d %d %d %d\n",tab[i][0],tab[i][1],tab[i][2],tab[i][3],tab[i][4],tab[i][5]);
} else {
printf("Error entering values.. (Enter numbers). \n");
while (getchar() != '\n'){}
i--;
}
}
return 0;
}
Unclear why OP's code failed without posting input used and prior code.
How to fix it?
Use fgets() to read a line of user input. Avoid mixing scanf() with fgets() in prior code. Then parse the buffer. Use " %n" at the end to look for success and extra text.
int tab[4][6];
char buf[6*12 * 2]; // Use a buffer twice expected max needs
for (int i = 0; i < 4; i++) {
while (1) {
if (fgets(buf, size buf, stdin) == NULL) {
return "Failed to read enough data"; // Handle end-of-file in some fashion
}
int n = 0;
sscanf(buf, "%d%d%d%d%d%d %n",
&tab[i][0], &tab[i][1], &tab[i][2], &tab[i][3], &tab[i][4], &tab[i][5], &n);
if (n > 0 && buf[n] == 0) {
break; // Success!
}
printf("Error - bad input, try again: ");
}
}
I need to create an array of ints of an unknown size and pass them all. My code looks like this:
int FillTable(int a[], int max){
int i;
int x = 0;
int m = 0;
for (i = 0; i < max; i++){
printf("Fill the table with integers: ");
scanf("%d", &m);
if (m != "" && m != NULL){
a[i] = m;
}else if (m != "" && m == NULL){
a[i] = 0;
}else{
break;
}
}
printf("\n");
return 0;
}
I know you can pass multiple ints separated by spaces with something like:
scanf("%d %d %d", &var1, &var2, &var3);
But I don't know how to pass a number of integers that I don't know how many will be there. Could I create a string with a bunch of %d and just repeat that for max times? I don't know, but right now, I just ask for ints until the array is full, and I need to be able to have the array be smaller than max if the user doesn't enter in enough values. Does anyone have any ideas as to how I would go about scanning for an unknown number of integers?
Does anyone have any ideas as to how I would go about scanning for an unknown number of integers?
This calls for Dynamic memory allocation!
One way of going with scanning unknown number of integers is, firstly allocate an integer array with size to hold max number of integers.
How to know whether user has ended his input?
If you are only scanning in positive integers from user at array entries then prompt him to end his input by inputting a negative number
or if you are sure about the range of input entries then break out of loop, when user enters input out of range
Example: (considering user inputs only positive numbers)
//creating a large enough array to store user inputs
int *array = malloc(sizeof(int) * max);
//check if memory was allocated or not
if(array == NULL)
{
printf("memory allocation problem!");
exit(1);
}
//integer to make note of size of array or you can use the sizeof() function instead
int size_of_array = 0;
for (i = 0; i < max; i++)
{
printf("Fill the table with integers: ");
if(scanf("%d", &m) != 1) //check for scanf return value
{
printf("wrong input, try again");
char consume; //to consume the character
scanf("%c", &consume);
i--;
continue;
}
if (m > 0) //if positive number, accept
{
array[i] = m;
size_of_array++;
}
else //else break out of scanning
{
break;
}
}
//do the program.....
//don't for get to free the memory at the end
free(array);
here's a working example: https://ideone.com/BHN4sk
You are trying to do something that is not necessary. To predict the size of the array and reallocate the appropriate exact size would be computationally more expensive (in terms of cpu time) so that benefit of saving the memory that you already had allocated is not enough.
The size of the array in c is stored somewhere that not necessarily has anything to do with the array itself. So you simply need to know how many of the array elements are interesting for the program and nothing else.
You could have something like
struct Array {
int *data;
size_t size;
size_t count;
};
where size is the total size of the array, count is the number of elements in the array and data are the elements. I use this pattern a lot and it's useful, specially if combined with realloc() as it saves from unecessarilly reallocating memory too many times which is expensive at the cost of using slightly more memory than actually needed.
But systems today have way more memory than can be used (except if you use Android Studio, which can use as much memory as your computer has).
First, m != "" && m != NULL probably does not do what you think it does. You're probably coming from a different language. What (I think) that statement does is compare the value in the integer variable m to the address of the string literal "" and then compare it to NULL (which evaluates to 0).
Second, scanf by default reads until either a space or a newline.
scanf returns a negative number on failure, so your code should look like this:
for (i = 0; i < max; i++){
printf("Fill the table with integers: ");
if(scanf("%d", &m) > 0) {
a[i] = m;
}
else {
break;
}
}
I left out the a[i] = 0 branch because I don't understand what you wanted there.
Also, you never use the variable x - unless there is more code that you left out.
your problem isn't understand for me properly,however i think this will be helped to you
int arraySize = 200; // Or whatever
int *array_ = malloc(arraySize * sizeof(int));
use this and the pass the *array_ as parameter,first defined array size or get array size as a user input,and run a for loop till size of array
You should decide how the user can stop his input (and include this info in your prompt). A quick-and-dirty way would be "enter anything that is not a number". I chose this way of terminating input, because it's easy to implement (hence, quick and dirty):
printf("Fill the table with integers; terminate with 'x':\n");
for (i = 0; i < max; i++)
{
int result = scanf("%d", &a[i]);
if (result != 1)
break;
}
Note:
The prompt tries to be user-friendly
The scanf function puts the number straight into the array, without using any intermediate variable
The scanf function returns how many numbers it read, which is normally 1; if it's not 1, then the user entered x or anything else
When the code finishes, i holds the number of iterations, which shows how many numbers were read from the user.
Your input function should return the size of the array:
return i; // instead of "return 0"
You might also want to clean the stdin buffer - discard anything that the user entered to terminate the array:
while (getchar() != '\n')
{
// do nothing - keep consuming input until end-of-line
}
I'm currently trying writing a program using C (very new to C - only been learning it for 2 weeks), and I wanted to get a string of input from the user by stdin, in which the string has a char, followed by 2 floats (each has space in between). Example would be: "y 2.1 1.1".
My question is how can I obtain and store the 3 inputs, while making sure the first is a char, and the following two inputs are floats?
Stick with sscanf(), but don't forget to check its return value (look here). What really happens for input "y 1u 1" is that sscanf will read and store the char, which is valid, then it will read and store the int 1, which is valid, and then stop, because "u" does not match the format string.
Below is example code (using scanf() rather then fgets() and sscanf()).
char in1;
int in2,in3;
int retval;
/*
char array[100] = {'\0'};
fgets(array, 100, stdin);
retval = sscanf(array, "%c %d %d", &in1, &in2, &in3);
*/
retval = scanf("%c %d %d", &in1, &in2, &in3);
printf("Scanned %d items\n", retval);
printf("Here they come: ");
if(retval > 0) {
printf("%c ", in1);
}
if(retval > 1) {
printf("%d ", in2);
}
if(retval > 2) {
printf("%d", in3);
}
putchar('\n');
How can I obtain and store the 3 inputs, while making sure the first is a char, and the following two inputs are ints?
problem with this code is that there are extra spaces at the very end, and I don't know how to get rid of it.
A simple way to use sscanf() and check if there is extra anything after the scanned variable is to use "%n" to record the location of the scan at that point.
char in1;
int in2, in3;
int n = 0;
sscanf(array,"%c %d %d%n", &in1, &in2, &in3, &n);
if (n > 0 && (array[n] == '\n' || array[n] == '\0')) {
Success(in1, in2, in3);
}
It is always important to check the results of sscanf(). One way is to check its return value which should be 3 here. Unfortunately that does not tell us if anything exist after in3. By setting n == 0 and then testing n > 0, code knows that scanning proceeded all the way successfully to "%n". Code can also test what character the scanning stopped at.