Provide integer arrays as input from command line - c

I'm writing a program to access a bin packing algorithm function from a library, I haven't done much with it since college so my C is a bit rusty. The function I'm calling requires I pass in 3 different integer arrays. I'll be calling this from the command line. Should I use argv? Or STDIN? The input arrays could potentially be 50 to 100 elements each. Either way I suppose I will have to write something to parse the strings and get them into arrays, is there an easy way to do that?

For big arrays, I'd rather use standard input, as there are usually operating system limits to how many arguments you can have.
You will also need some kind of input format. Let's say the first number n is the number of elements in the first array, followed by the element values, and so on. Then I'd do something like:
#include <stdlib.h>
#include <stdio.h>
int main()
{
// you need to implement read_number yourself
int n = read_number(stdin);
// allocate array
int *array = (int*) malloc(n*sizeof(int));
// read n numbers into array
for ( int i=0; i < n; ++i )
array[i] = read_number(stdin);
// and so on...
}
You get the general idea. You'd either have to implement read_number yourself or find examples on the net on how to do it. You will need to discern individual numbers somehow, e.g. by parsing each digit up to the next white space character. Then you can separate each digit on stdin by space characters.
For instance, you can use #ypnos suggested scanf solution below.

For that amount of elements you should use stdin. Nobody will type them in by hand anyway and ./program < file is as easy as it gets.
The parsing is no big deal with scanf. Just define that your input should include the number of elements before all the numbers forming an array. Then you can scanf("%d", &elemcount), and then for-loop over elemcount, again using scanf.
The beauty of it is that scanf will deal with all the whitespaces, newlines etc. the user may put in between the numbers of elements and the other numbers.

Related

How to store multiple sets of strings in a character array

I am trying to store a given input number of sets of strings in a 3D character array, but couldn't.
Is it even possible using char arrays or should i use any other concept like data structures......?
int main()
{
int i,j,T,N[10];
char word[10][10][10];
scanf("%d",&T);/* No of test cases*/
for(i=0;i<T;i++)
{
scanf("%d",&N[i]); /*No of strings*/
for(j=0;j<N[i];j++)
scanf("%s",word[i][j]); /* reading the strings*/
}
return 0;
First: a "3D character array" is better thought of as a "2D string matrix" in this case.
And yes, of course it's very possible.
There are some weaknesses with your code that might trip it up, hard to say since you don't show a full test case with the input data you provide.
scanf() can fail, in which case you cannot rely on the variables having values
scanf() with %s will stop on the first whitespace character, which might cause your scanning code to become very confused
You don't limit the size of string you scan, but only provide 10 bytes of buffer space per string, so easy to get buffer overruns.
A better solution would be to check that the scanning succeeded, and make each string be on a line on its own, and read full lines using fgets() into an appropriately-sized buffer, then perhaps copy the part you want to keep into place in the matrix.

What is the proper way to populate an array of Strings in C, such that each string is a single element in the array

I'm trying to initialize a 2D array of strings in C; which does not seem to work like any other language I've coded in. What I'm TRYING to do, is read input, and take all of the comments out of that input and store them in a 2d array, where each string would be a new row in the array. When I get to a character that is next line, I want to advance the first index of the array so that I can separate each "comment string". ie.
char arr[100][100];
<whatever condition>
arr[i][j] = "//First comment";
Then when I get to a '/n' I want to increment the first index such that:
arr[i+1][j] = "//Second comment";
I just want to be able to access each input as an individual element in my array. In Java I wouldn't need to do this, as each string would already be an individual element in a String array. I've only been working with c for 3 weeks now, and things that I used to take for granted as being simple, have proven to be quite frustrating in C.
My actual code is below. It gives me an infinite loop and prints out a ton of numbers:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int MAXLENGTH = 500;
int main(){
char comment[MAXLENGTH][MAXLENGTH];
char activeChar;
int cIndex = 0;
int startComment = 0;
int next = 0;
while((activeChar = getchar()) != EOF){
if(activeChar == '/'){
startComment = 1;
}
if(activeChar == '\n'){
comment[next][cIndex] = '\0';
next++;
}
if(startComment){
comment[next][cIndex] = activeChar;
cIndex++;
}
}
for(int x = 0 ; x < MAXLENGTH; x++){
for (int j = 0; j < MAXLENGTH; j++){
if(comment[x][j] != 0)
printf("%s", comment[x][j]);
}
}
return 0;
}
The problem you are having is that C was designed to be essentially a glorified assembler. That means that the only stuff it has 'built-in' are things for which there is an obvious correct way to do it. Strings do not meet this criteria. As such strings are not a first-order citizen in c.
In particular there are at least three viable ways to deal with strings, C doesn't force you to use any of them, but instead allows you to use what you want for the job at hand.
Method 1: Static Array
This method appears to be similar to what you are trying to do, and is often used by new C programmers. In this method a string is just an array of characters exactly long enough to fit its contents. Assigning arrays becomes difficult, so this promotes using strings as immutables. It feels likely that this is how most JVM's would implement strings. C code: char my_string[] = "Hello";
Method 2: Static Bounded Array
This method is what you are doing. You decide that your strings must be shorter than a specified length, and pre-allocate a large enough buffer for them. In this case it is relatively easy to assign strings and change them, but they must not become longer than the set length. C code: char my_string[MAX_STRING_LENGTH] = "Hello";
Method 3: Dynamic Array
This is the most advanced and risky method. Here you dynamically allocate your strings so that they always fit their content. If they grow too big, you resize. They can be implemented many ways (usually as a single char pointer that is realloc'd as necessary in combination with method 2, occasionally as a linked list).
Regardless of how you implement strings, to C's eyes they are all just arrays of characters. The only caveat is that to use the standard library you need to null terminate your strings manually (although many [all?] of them specify ways to get around this by manually specifying the length).
This is why java strings are not primitive types, but rather objects of type String.
Interestingly enough, many languages actually use different String types for these solutions. For example Ada has String, Bounded_String, and Unbounded_String for the three methods above.
Solution
Look at your code again: char arr[100][100]; which method is this, and what is it?
Obviously it is method 2 with MAX_STRING_LENGTH of 100. So you could pretend the line says: my_strings arr[100] which makes your issue apparent, this is not a 2D array of strings, but a 2D array of characters which represents a 1D array of strings. To create a 2D array of strings in C you would use: char arr[WIDTH][HEIGHT][MAX_STRING_LENGTH] which is easy to get wrong. As above, however, you have some logic errors in your code, and you can probably solve this problem with just a 1D array of strings. (2D array of chars)
comment is a 2D array of chars, which are single characters. In C, a string is simply an array of characters, so your definition of comment is one way to define a 1D array of strings.
As far as the loading goes, the only obvious potential problem is that you don't ever reset startComment to zero (but you should use a debugger to make sure it's being loaded correctly), however your code to print it out is wrong.
Using printf() with a %s tells it to start printing the string at whatever address you give it, but you're giving it individual characters, not whole strings, so it's interpreting each character in each string (because C is a horrible, horrible language) as an address in RAM and trying to print that RAM. To print an individual character, use %c instead of %s. Or, just make a 1D for loop:
for(int x=0; x<MAX_LENGTH; X++)
printf("%s\n", comment[x])
It's also a bit confusing that you use the same MAX_LENGTH for the number of lines in the array and the length of the string in each line

Identyfying prefix in the same string as a suffix

Eg-
maabcma is valid because it contains ma as a proper prefix as well as a proper suffix.
panaba is not.
How do I find out if a word is valid or not as above in C language?
I'm not very good at string operations. So, please help me out with a pseudocode.
Thanks in advance.
I'm completely lost. T=number of test cases.
EDIT: New code. My best code so far-
#include<stdio.h>
#include<string.h>
void main()
{
int i,T,flag=0;
int j,k,len=0;
char W[10],X[10];
scanf("%d",&T);
for(i=0;i<T;i++)
{
scanf("%s",W);
for(len=0;W[len]!='\0';len++)
X[len]=W[len];
X[len]='\0';
for(j=len-1;j>=0;j--)
for(k=0;k<len;k++)
{
if(X[k]!=W[j])
flag=0;
else if((j-k)==(len-1))
flag==1;
}
if (flag == 1)
printf("NICE\n");
else
printf("NOT\n");
}
}
Still not getting the proper results. Where am I going wrong?
The thing is you are only setting the value of flag if a match exists, otherwise you must set it to 0. because see, if I have:
pammbap
my prefix is pam and suffix is bap.
According to the final for loop,
p and a match so flag is set to 1.
but when it comes to b and m it does not become zero. Hence, it returns true.
First, void is not a valid return type for main, unless you are developing for Plan 9.
Second, you should get into the habit of checking the return value of scanf() and all input functions in general. You can't rely on the value of T if the user does not input a number, because T is uninitialised. On that same note, you shouldn't use scanf with an unbounded %s scan operation. If the user enters 20 characters, this isn't going to fit into the ten character buffer that you have. An alternative approach is to use fgets to get a whole line of text at once, or, to use a bounded scan operation. If your array fits 10 characters (including the null terminator) then you can use scanf("%9s", W).
Third, single-character variable names are often very hard to understand. Instead of W, use word, instead of T, use testCount or something similar. This means that someone looking at your code for the first time can more easily work out what each variable is used for.
Most importantly, think about the process in your head, and maybe jot it down on paper. How would you solve this problem yourself? As an example, starting with n = 1,
Take the first n characters from the string.
Compare it to the last n characters from the string
Do they match?
If yes, print out the first n characters as the suffix and stop processing.
If no, increment n and try again. Try until n is in the middle of the string.
There are a few other things to think about as well, do you want the biggest match? For example, in the input string ababcdabab, the prefix ab is also the suffix, but the same can be said about abab. In this case, you don't want to stop processing, you want to keep going even if you find a prefix, so, you should just store the length of the largest prefix that is also the suffix.
Second-most-importantly, running into hurdles like this is incredibly common when learning C, so don't let this put a dampener on your enthusiasm, just keep trying!

C multidimensional array size using scanf

I'm having some trouble using multidimensional arrays for a program. Essentially, the program uses scanf to read a user ID and a string of chars from a redirected file. the file format is a three digit user ID, a space, and a string of chars representing the answers to multiple choice problems on a test on each line, eg.
111 dabac
102 dcbdc
251 dbbac
The problem I'm running into is that I don't know how many users there are, and I can't read the file data multiple times. I've tried using
for (lineNumber = 0; lineNumber != -1; lineNumber++)
{
int result = scanf("%d ", &data);
if (result == EOF)
break;
for(i = 0; i < numProblems; i++)
{
scanf("%c", &input);
}
to get the number of lines in the file, then set the size of the array. The array is then passed to another function that reads the data, using the same for loop but with
input = arrayName[numProblems][lineNumber];
in the second for loop. The issue I'm running into is that scanf can only read the data from the file once, and I can't store the data in the array until I initialize it, which requires me to know how many users there are.
The way I have it set up, the program can either find the number of lines(users) or store the data in the array (if I set the size to an arbitrary number), but not both.
I have to use scanf because the filename isn't constant (and also this is for a class... the professor requires scanf to be used), and I can't figure out how to get the number of lines in the file and still be able to read the data. If anyone knows of a workaround to either find the number of lines without using scanf, or to read the data twice, I would really appreciate some help. If it would help to post the entire program, I can do that as well.
Thank you,
Erik
There are multiple ways to do this. I would recommend a linked list using structs, and keeping a count of what has been read so far.
If you really want to continue using arrays, allocate the array using malloc first, and then reallocate the array using realloc. You'll have a running count of the size of the array for reallocation.
it should be something like this:
POINTER *array = realloc(orig_array_pt, size);
if (array == NULL)
{
// realloc failed
}
else
{
orig_array_pt = array;
}
As long as the input is an actual file (and not a terminal or some other device), you can use rewind(stdin); to set the FILE pointer back to the beginning of the file...
Luckily scanf() will parse the whole line into multiple variables in one pass. Try something more like
scanf( "%d %s", &uid, answers );
Just count the number of times you're able to successfully parse data out of the stdin and call that your lineNumber count ( if you even need to know the total number of lines ).

getting numbers from stdin to an array in C

I'm trying to get numbers from stdin to an array. the first number in stdin is the number of elements in the array (the number can be any int).
I did this to get the first number:
while(c=getchar()!=' '){
n*=10;
n+=atoi(c);
}
And then created an array of size n.
Now I need to go through all the rest
while(c=getchar()!=EOF)
and add numbers to the array. The numbers are separated by \t and sometimes \n as well.
How would I do that? I've been thinking for an hour and still haven't got a working code.
Any help?
Thanks!
Unless you're feeling particularly masochistic (or can't due to homework requirements), you'd normally do it using scanf:
int n;
int *numbers;
scanf("%d", &n);
numbers = malloc(n * sizeof(*numbers));
for (int i=0; i<n; i++)
scanf("%d", &numbers[i]);
For more robust error handling, you frequently want to read a line at a time using fgets, then parse that into individual numbers using sscanf (or something similar).
As an aside: no you should not cast the return from malloc to int *. It's neither necessary nor desirable in C. Just #include <stdlib.h>, and assign the result as shown above. If your compiler is giving you a warning (or error) about a conversion, that means one of two things is happening: either you've forgotten to #include <stdlib.h> as required, or else you're actually compiling as C++. If you're writing C++, write real C++, which means you shouldn't be using malloc at all.

Resources