Array pointer while loop input - c

I am trying to write a program to check for duplicate input from a programmable handheld barcode scanner, I am programming it to be able to scan 2000 barcodes.
I am new to c Programming, I am trying to take an input and put it into the array and increase the pointer to the next with every loop.
Example: int Array [10];
I want to scanf() into Array location 0 on the first loop then increment by 1 location to location 2 etc every time the while loops runs. Please help, your help is much appreciated.
#include <stdio.h>
int main ()
{
int i,j,k=1,arr[2000],ArrSize=2000;
//Welcome message
printf("Welcome to Yamato Transport (S) Pte. Ltd.\n");
printf("Barcode checker Ver 1.0\n");
while (k>=2000,k++)
{
//Scanner Input
for(i=0;i<ArrSize;i++)
{
scanf("%d",&arr[i]);
}
//Duplicate Logic
printf("Duplicate Barcodes: ");
for(i=0; i<ArrSize; i++)
{
for(j=i+1;j<ArrSize;j++)
{
if(arr[i]==arr[j])
{
printf("%d\n",arr[i]);
}
}
}
//Remove single duplicate
//Clear Screen
}
return 0;
}

The first problem with your code is this:
int i,j,k=1,...
...
while (k>=2000,k++)
^^^^^^
ups...
This will give the warning "left-hand operand of comma expression has no effect" which actually means that the line is the same as:
while (k++)
That will keep looping until you have integer overflow (which is undefined behavior). So you don't want to do that.
Since you initialize k to 1, I assume that you wanted to do:
while (k++ < 2000)
Now let's assume that you want:
while (k++ < 2000) // Will loop approx 2000 times
{
//Scanner Input
for(i=0; i< ArrSize; i++) // Will loop 2000 times
{
scanf("%d",&arr[i]);
}
So in the end your program calls scanf 2000 x 2000 = 4.000.000 times. Is that what you want? The purpose of the outer while is unclear.
Your program first reads 2000 integers and afterwards it seems you want to remove duplicates. That's a bad approach as you may end you doing a lot of memory move whenever you need to remove a duplicate element from the array.
A better approach is to check whether a newly scanned value is a duplicate before inserting it in the array. That could look something like:
for(i=0; i < ArrSize; )
{
int tmp;
if (scanf("%d", &tmp) != 1)
{
// Input error
exit(1);
}
// Check if tmp is already in the array
int duplicate = 0;
for (int j = 0; j < i; ++j)
{
if (tmp == arr[j])
{
duplicate = 1;
break;
}
}
if (duplicate)
{
printf("dup found\n");
}
else
{
arr[i] = tmp;
++i;
}
}
This should give you ArrSize unique elements.
Notice: In order to check if something is a duplicate, you'll need to scan through the array from start to the current number of elements. To improve performance you could consider another approach, e.g. a sorted tree, hash tables, etc so that check for duplicates can be done much faster. This gets more important as the number of array elements increase.

So half the problem is solved, I am still not sure how do I increase the pointer to the next position so on the next loop it will store another barcode number which will then be passed to the duplicate checker for checking then repeat the loop for the next scan.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i,j,k=1,arr[2000],counter=1;
//Welcome message
printf("Welcome to Yamato Transport (S) Pte. Ltd.\n");
printf("Barcode checker Ver 1.0\n");
while (k++ < 2000) // Will loop approx 2000 times
{
//Scanner Input
printf("Scan barcode\n");
for(i=0; i< counter; i++) // Will loop 1 time
{
scanf("%d",&arr[i]);
}
//check for duplicates
for(i=0; i < counter; )
{
int tmp;
if (scanf("%d", &tmp) != 1)
{
// Input error
exit(1);
}
// Check if tmp is already in the array
int duplicate = 0;
for (int j = 0; j < i; ++j)
{
if (tmp == arr[j])
{
duplicate = 1;
break;
}
}
if (duplicate)
{
printf("Duplicate Barcode\n");
}
else
{
arr[i] = tmp;
++i;
}
}
}
return 0;
}

Related

How to input for arrays I don't know the length of?

I'm trying to make a program that accepts the number of students enrolled to an exam, and how many points each of them got. I try to loop the inputs but it gives seemingly random numbers in output
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int studenti;
scanf("%d", &studenti);
printf("%d ", studenti);
int niza[studenti];
for (int i = 1; i <= studenti; i++){
scanf("%d", &niza[i]);
i++;
printf("%d ",niza[i]);
}
}
What am I doing wrong? Is there another way to add array elements without knowing how big the array will be beforehand because I don't know how big they are when I pass the checks on my uni website.
The primary issue is that the for loop begins with 1 and continues to i <= studenti. In C, arrays begin with index '0' and the final index in this example is studenti - 1.
Another issue is the for loop increments i and there is an i++; in the body of the loop. i is incremented twice.
Check the return from scanf. It returns the number of items successfully scanned. Here that would be 1, 0 or EOF.
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int studenti = 0; // initialize
if ( 1 == scanf("%d", &studenti)) { // successful scan
printf("%d ", studenti);
int niza[studenti]; // variable length array
for (int i = 0; i < studenti; i++) { // start from index 0
if ( 1 == scanf("%d", &niza[i])) {
printf("%d ",niza[i]);
}
else { // scanf returned 0 or EOF
fprintf ( stderr, "problem scanning array element\n");
return 2;
}
}
}
else { // scanf returned 0 or EOF
fprintf ( stderr, "problem scanning\n");
return 1;
}
printf("\n");
return 0;
}
If you don't know the length, you should probably create a linked list instead of a static array, and malloc another list element for each student.

How to ask for infinite user inputs in C?

I want to create an infinite loop such that I'm able to ask the user for up to 2 inputs, and store them into an array (a) and then print these array values. I want it then to restart, and repeat this process of asking and repeating. With my current code, once I enter values and declare End of Function (EOF), the console infinitely prints out these values rather than restarting and asking for new values.
#include <stdio.h>
int main (void) {
int a[2];
int i = 0;
while (1 < 2) {
while(scanf("%d", &a[i]) != EOF) {
i++;
//i == number of inputs (max is 2)
}
int j = 0;
while(j < i) {
printf("%d ", a[j]);
j++;
}
}
return 0;
}
My hypothesis is that the scanf("%d", &a[i]) value has not reset after being declared as being EOF but I'm not entirely sure on how to do that.
You have undefined behavior because of accessing out of bound.
You need to reset the i on each iteration or even better limit the scope of i to each iteration.
int i = 0;
while (1) {
i = 0; // reset i
while(scanf("%d", &a[i]) == 1 && i < 2) {
i++;
//i == number of inputs (max is 2)
}
...
}

My C program to find closest pair of numbers from user input is not printing the right output?

I am trying to find the closest pair of numbers entered by the user. My C code isn't working right and I can't figure out what's wrong. I think it might have something to do with storing the values but I don't know where to go from here.
#include <stdio.h>
#include <math.h>
int main()
{
int i, j,arr[50], first,second;
//loop input
for(i=0;i<50;i++) //loop 50 times
{
scanf("%d", &i); //scan
//break if i=-1
if (i==-1)
break;
//if not print
}
//2nd num - 1st num < 3rd num-1st num, closest = 1st and 2nd num
//i[0]=num1, j[0+i]=2nd num, i= 4 , 5, 7, ans=arr,
//if j[0+i]-i[0]= ans < j[0+i]-i[i]=ans
//arr[i]=8,2,17,4,25
for(i=0;i<50;i++)
{
for(j=i+1;j<50;j++)
{
if(arr[j]-arr[i]<arr[j+1]-arr[i])
{
first = arr[i];//3
second = arr[j+1];//5
}
}
}
printf("%d %d\n", first, second);
return 0;
}
Don't post it as answer, prefer editing your code instead. Anyway, the problem is here :
for (j = i + 1; j < len; j++)//j<i <-why is it wrong?
How isn't it wrong? You've initialised j with the value i+1. How's it supposed to be ever less than i? And due to that, it's picking up values from outside the array and providing you with unexpected results.
The correct form is :
for (j = 0; j < i; j++)
The problem is with this chunk of code. You're scanning in the counter variable i instead of array. And then you're manipulating stuff using array arr. Why should that work in any scenario?
for(i=0;i<50;i++) //loop 50 times
{
scanf("%d", &i); //scan
//break if i=-1
if (i==-1)
break;
//if not print
}
And i can never be -1 unless it's a miracle.

Sorting array from typedef struct in C

Problem: Trying to sort an array coming from a typedef struct I created (phonebook).
Goal: Trying to build a phonebook that allows users to add, delete, sort, and print the phonebook.
Where I'm at: I've got everything working except the sort. I've cobbled together a sort function from reading various web forums/examples, but can't get it to work.
Issue I'm having: After adding entries (which works fine), if you try to sort entries, the function zeroes out values of those entries and when you print the phonebook, it shows all entries as blank. It should sort them alphabetically by last name.
Here's the sort algorithm I have in place:
void Sort (phone phonebook[])
{
phone temp;
int i; int j;
for (i=0; i<19; i++)
{
for (j=i+1; j<19; j++)
{
if (strcmp(phonebook[i].Surname, phonebook[j].Surname) > 0)
{
temp=phonebook[i];
phonebook[i]=phonebook[j];
phonebook[j]=temp;
}
}
}
}
Any ideas?
Full code here:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//typedef struct to define what's in the phonebook
typedef struct PhoneBookContacts
{
char Name[20];
char Surname[20];
char PhoneNumber[20];
} phone;
//Function prototypes
void AddEntry (phone[]);
void DeleteEntry (phone[]);
void PrintEntry (phone[]);
void Sort (phone[]);
int counter = 0; //Global counter variable used to keep track of number of contacts
//Begin main function
int main (void)
{
phone phonebook[20]; //Phonebook instance
char userChoice; //Variable to use to select menu choice
while (userChoice != 'Q') {
printf ("***************\n");
printf ("Please enter a command:\n");
printf("'A': Add an entry\n");
printf("'D': Delete an entry\n");
printf("'S': Sort entries\n");
printf("'P': Print the phonebook\n");
printf("'Q': Quit\n");
printf ("***************\n");
scanf("%s", &userChoice); //Stores menu choice into variable userChoice
// Add Contact
if (userChoice == 'A')
AddEntry(phonebook);
//Remove Contact
if (userChoice == 'D')
DeleteEntry (phonebook);
//Print Contacts
if (userChoice == 'P')
PrintEntry(phonebook);
//Sort Contacts
if (userChoice == 'S')
Sort(phonebook);
//Quit
if (userChoice == 'Q') {
printf("Phonebook will now quit.");
return 0;
}
}
}
//Function Definition to Add Contacts to the Phonebook
void AddEntry (phone phonebook[]) {
counter++; //global counter increase
printf("\nFirst Name: ");
scanf("%s", phonebook[counter-1].Name); //counter-1 b/c arrays start at 0
printf("Last Name: ");
scanf("%s", phonebook[counter-1].Surname);
printf("Phone Number (XXX-XXX-XXXX): ");
scanf("%s", phonebook[counter-1].PhoneNumber);
printf("\n%s added to phonebook\n", phonebook[counter-1].Name); //tell user friend added
}
void DeleteEntry (phone phonebook[])
{
int x = 0;
char deleteName[20]; // Temp string to compare to existing phonebook
char deleteSurname[20]; //temp string
char nullStr[20] = {"\0"}; // empty string to remove phonenumber
printf("\nEnter name: ");
scanf("%s", deleteName); //place into temp string
printf("Enter Surname: ");
scanf("%s", deleteSurname); //place into temp string
for (x = 0; x < counter; x++)
{
if (strcmp(deleteName, phonebook[x].Name) == 0) //compare deleteName to phonebook.Name
{
for (x = 0; x < counter; x++)
{
if (strcmp(deleteSurname, phonebook[x].Surname) == 0) //If deleteSurname matches phonebook.Surname
{
strcpy(phonebook[x].Name, nullStr); //Put null into Name
strcpy(phonebook[x].Surname, nullStr); //Null into Surname
strcpy(phonebook[x].PhoneNumber, nullStr); //Null into PhoneNumber
printf("Contact removed from phonebook.\n");
counter--;
break;
}
}
}
else printf("Invalid entry--try again.\n");
}
}
// Function def to print contacts
void PrintEntry (phone phonebook[]) {
int x = 0;
printf("\nPhonebook entries:\n");
for ( x = 0; x < counter; x++) {
printf("\n(%d)\n", x+1); //Show contact number
printf("Name: %s %s\n", phonebook[x].Name, phonebook[x].Surname); //Name
printf("Number: %s\n", phonebook[x].PhoneNumber); //Number
}
}
void Sort (phone phonebook[]) {
phone temp;
int i; int j;
for (i=0; i<19; i++) {
for (j=i+1; j<19; j++) {
if (strcmp(phonebook[i].Surname, phonebook[j].Surname) > 0) {
temp=phonebook[i];
phonebook[i]=phonebook[j];
phonebook[j]=temp;
}
}
}
}
You can use the already implemented sorting function qsort function available at stdlib.h:
int SortFunc(void* a, void* b) {
phone *p1 = (phone*)a;
phone *p2 = (phone*)b;
return strcmp(p1->Surname, p2->Surname);
}
void Sort (phone phonebook[]) {
qsort(phonebook, counter, sizeof(phone), &SortFunc);
}
The function is usually Quicksort, but that's up to the C library implementation to decide.
Update:
The blank listing is because the sorting is reversed and always sorting all the 19 items of the phonebook, comparing the empty ones against the real ones. If you have less than 19 entries on the phonebook, the actual data is going to be present at the end of the phonebook array.
Your original Sort function was always working almost OK. Just change the end condition on the two for.
void Sort (phone phonebook[]) {
phone temp;
int i; int j;
for (i=0; i<counter; i++) {
for (j=i+1; j<counter; j++) {
if (strcmp(phonebook[i].Surname, phonebook[j].Surname) > 0) {
temp=phonebook[i];
phonebook[i]=phonebook[j];
phonebook[j]=temp;
}
}
}
}
I've also updated my Sort above.
First things first, you have a buffer overflow issue here:
char userChoice;
:
scanf("%s", &userChoice);
That scanf will write two bytes when you enter one character (the character plus a null terminator). This corrupted the first name of the first phonebook entry in my environment but, since it's undefined behaviour, it could do anything!
You can get around this by using:
char userChoice[] = "something that's not Q";
:
scanf("%s", userChoice);
:
if (*userChoice == 'A') // for all of these.
That won't stop a buffer overflow if you enter enough text but it will if you limit yourself to single character commands. If you want a truly robust user input function, see here.
Now to your specific problem. It looks like you have a bit of a bubble sort going on there, but your logic is slightly off. Assuming you don't want to use qsort (which would be the better way for real code), you just need to fix up a couple of things.
Your outer loop is okay, as is your inner loop, but the inner loop body should be comparing elements j and j+1, not j and i. That's because it works by swapping adjacent elements if they're out of order.
In addition, a forward focused bubble sort will place the highest element at the end of the list on the first pass, so you can't start j at i+1 on the second pass, simply because the first element may not be correct yet.
The following psuedo-code is your classic bubble sort:
didSwap = true
while didSwap:
didSwap = false
for i = 0 to lastidx - 1:
if array[i] > array[i+1]:
temp = array[i]
array[i] = array[i+1]
array[i+1] = temp
didSwap = true
Read that, understand how it works, then implement it on your own. If you have trouble with that, I've included a working version below:
void Sort (phone phonebook[]) {
phone temp;
int i; int didSwap;
didSwap = 1;
while (didSwap) {
didSwap = 0;
for (i = 0; i < counter - 1; i++) {
if (strcmp(phonebook[i].Surname, phonebook[i+1].Surname) > 0) {
temp=phonebook[i];
phonebook[i]=phonebook[i+1];
phonebook[i+1]=temp;
didSwap = 1;
}
}
}
}
for (i=0; i<19; i++)
{
for (j=i+1; j<19; j++)
{
if (strcmp(phonebook[i].Surname, phonebook[j].Surname) > 0)
{
temp=phonebook[i];
phonebook[i]=phonebook[j];
phonebook[j]=temp;
}
}
}
Three problems with your code. First is the logic of your algorithm. Bubble sort works by fixing the order of two adjacent element. In your code, after the first iteration of your inner for loop, it's not going to compare two adjacent elements.
The second problem, again in sorting algorithm, your counters i and j are both going to 19, even when there is less entries than that. This might mess up the sorting as they will be reading invalid(uninitialized) entry. you should check the upper bound for the counter.
The next one is in the deletion
if (strcmp(deleteName, phonebook[x].Name) == 0) //compare deleteName to phonebook.Name
{
for (x = 0; x < counter; x++)
{
if (strcmp(deleteSurname, phonebook[x].Surname) == 0) //If deleteSurname matches phonebook.Surname
{
strcpy(phonebook[x].Name, nullStr); //Put null into Name
strcpy(phonebook[x].Surname, nullStr); //Null into Surname
strcpy(phonebook[x].PhoneNumber, nullStr); //Null into PhoneNumber
printf("Contact removed from phonebook.\n");
counter--;
break;
}
}
}
The code above will not check properly whether the first and last name since you're checking them separately. You only need one for loop with if( strcmp(deleteSurname, phonebook[x].Surname) == 0 && strcmp(deleteName, phonebook[x].Name) == 0 )

linear searches in 2d arrays

#define NUMLEG 7
int Search_type(char leg_type[6][10], int travel_int[6][15], int trip_num);
c = Search_type(type,leg_type, travel_int, trip_num);
if (c == -1)
printf("Destination not found.\n");
else
printf("Destination Found \nDestination Name:%s", travel_name[c]);
int Search_type( char type, char leg_type[6][10], int travel_int[6][15], int trip_num)
{
int i, n;
char target;
getchar();
printf("Please enter travel type you wish to search by:");
scanf("%c", &target);
for (i =0; i <trip_num; i++)
{
for ( n = 0; n < travel_int[i][NUMLEG]; n++)
{
if( leg_type[i][n] == target)
{
return i;
}
}
return -1;
}
}
This is a rip out of a function I'm currently working on from a project and for some strange reason I can't seem to get it to search properly, I know that its not the rest of the code but this area since all the other function works properly. So I decided to break this out of the code and test it.
I can't seem to get it to search after 1 row:
travel_int[i][NUMLEG] contains the number of legs
leg_type is where i store the char of each leg
I want it to search through the leg_type till it finds the specified character. Without pointers.
EDIT
For example
Trip#:1
Destination Name:Austin
Leg(#1):A
Leg(#2):T
Trip#:2
Destination Name:Florida
Leg(#1):S
Leg(#2):F
so
trip number = 2
travel_int stores 2 trips and each trip has 2 legs
leg type stores in the 2 leg types at the trip number
When I put in A or T it prints out Austin like it should but when I input S or F it return destination not found =/. Am I doing the search wrong, or is it the print statement that is wrong. Or is it where I'm place my return -1;.
(I would put up the code but its a bit long..)
In your nested loops you are returning -1 without doing complete search in the entire arrays.
Place return -1 outside all the for() loops.
for (i =0; i <trip_num; i++)
{
for ( n = 0; n < travel_int[i][NUMLEG]; n++)
{
if( leg_type[i][n] == target)
{
return i;
break;
}
}
} return -1
This would definitely make your program run correctly.And this is the only reason why you get the correct results when you search for trip #01.

Resources