I'm trying to verify ISBN numbers in C but when I run the program I get the following error: Disallowed system call: SYS_socketcall
This is for a homework assignment in a CS class. I've done all the work so it's not like I'm asking people to do my assignment for me. I'm just wondering why I'm getting this error as I'm new to the C language; I come from a Java background as well as some web programming languages. Anyways, here's the assignment description if it'll help:
Perform a check on the characters in an ISBN to verify correctness.
The check character is computed as follows:
First, compute the sum of the first digit plus two times the second digit
plus three times the third digit, ... , plus nine times the ninth digit. The
last character is the remainder when the sum is divided by 11. If the
remainder is 10, the last character is X. For example, the sum for
the ISBN 0-8065-0959-7 is
1*0 + 2*8 + 3*0 + 4*6 + 5*5 + 6*0 + 7*9 + 8*5 + 9*9 = 249
The remainder when 249 is divided by 11 is 7, the last character in the ISBN.
The check character is used to validate an ISBN.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int checkISBN( char[] );
#define size 18L
int main() {
int i,j;
char* s[size] = {
"0-8065-0959-7",
"0-534-37964-8",
"0-618-50298-X",
"0-8065-0959-8",
"0-534-37964-9",
"0-618-50298-5",
"0-534-37964-8",
"0-618-50298-X",
"032121353X",
"0321199553",
"0201794896",
"0870495275",
"0452264464",
"0536901562",
"158901104X",
"080801076X",
"80-902734-1-6"
"158901104X" };
for( i = 0; i < size; i++){
if( checkISBN( s[i] ) == 1 )
printf("%-15s is a valid ISBN \n",s[i]);
else
printf("%-15s is NOT a valid ISBN*****\n",s[i]);
}
putchar('\n'); //write a newline
system("pause");`enter code here`
return EXIT_SUCCESS;
}
int checkISBN( char s[] )
{
int result = 0;
int i;
int n = 1;
int sum = 0;
char ch[10];
int final[10];
int sizeOfArray = strlen(s);
for(i=0; i<sizeOfArray; i++){
if(s[i] == '-'){
++i;}
if(s[strlen(s)-1] == 'X'){
s[strlen(s)-1] = 10;}
ch[i] = s[i];
}
for(i=0; i<10; i++){
final[i] = atoi(&ch[i]);}
for(i=0; i<9; i++){
sum+= final[i]*n;
++n;}
int checkCharacter = sum%11;
if(checkCharacter == final[9]){
result = 1;}
return result;}
#include <ctype.h>
int checkISBN( char s[] ) {
int i, n = 1, sum = 0, checksum;
for(i=0; s[i]; ++i){
if(s[i] == '-')
continue;
if(n<10 && isdigit(s[i]))
sum += n++*(s[i] - '0');
else if(n==10){
if(s[i] == 'X')
checksum = 10;
else if(isdigit(s[i]))
checksum = s[i] - '0';
}
}
return sum % 11 == checksum;
}
also
"80-902734-1-6", //need comma
Related
I have an assignment which requires me to write a program that multiplies two large numbers that are each stored in an array of characters with the maximum length of 100. After countless efforts and debugging and multiplying 10 digit numbers step by step and by hand I have now written the following piece of messy code:
#include <iostream>
#include <string.h>
using namespace std;
const int MAX_SIZE = 100;
int charToInt(char);
char IntToChar(int);
long long int pow10(int);
bool isNumber(char[]);
void fillWith0(char[], int);
void multiply(char[], char[], char[]);
int main(){
char first_num[MAX_SIZE + 1], second_num[MAX_SIZE + 1], product[2 * MAX_SIZE + 1];
cout << "A =\t";
cin.getline(first_num, MAX_SIZE);
cout << "B =\t";
cin.getline(second_num, MAX_SIZE);
multiply(first_num, second_num, product);
cout << "A * B = " << product << endl;
return 0;
}
int charToInt(char ch){
return ch - '0';
}
char intToChar(int i){
return i + '0';
}
long long int pow10(int pow){
int res = 1;
for (int i = 0; i < pow ; i++){
res *= 10;
}
return res;
}
bool isNumber(char input[]){
for (int i = 0; input[i] != '\0'; i++){
if (!(input[i] >= '0' && input[i] <= '9')){
return false;
}
}
return true;
}
void fillWith0(char input[], int size){
int i;
for (i = 0; i < size; i++){
input[i] = '0';
}
input[i] = '\0';
}
void multiply(char first[], char second[], char prod[]){
_strrev(first);
_strrev(second);
if (isNumber(first) && isNumber(second)){
fillWith0(prod, 2 * MAX_SIZE + 1);
int i, j, k;
long long int carry = 0;
for (i = 0; second[i] != '\0'; i++){
for (j = 0; first[j] != '\0'; j++){
long long int mult = (pow10(i) * charToInt(first[j]) * charToInt(second[i])) + carry + charToInt(prod[j]);
prod[j] = intToChar(mult % 10);
carry = mult / 10;
}
k = j;
while (carry != 0){
carry += charToInt(prod[k]);
prod[k] = intToChar(carry % 10);
carry = carry / 10;
k++;
}
}
prod[k] = '\0';
_strrev(first);
_strrev(second);
_strrev(prod);
}
}
My problem is that it does not work with numbers that have more than 10 digits (1234567891 * 1987654321 works fine but nothing with more digits than that), as the output in those cases is a set of weird characters I presume the issue is somewhere something is overflowing and causing weird issues, although I have used long long int to store the only two numeric integers in the algorithm, doing so helped me bump from 6 digits to 10 but nothing more. Is there any suggestions or possibly solutions I can implement?
P.S. : As I mentioned before this is an assignment, so using libraries and other stuff is not allowed, I've already seen this implemented using vectors but unfortunately for me, I can't use vectors here.
The core mistake is using a long long int to store the intermediate multiplied number. Instead, use another char[] so the core of your multiply becomes simply:
for (i = 0; second[i] != '\0'; i++){
char scratch[2 * MAX_SIZE + 1];
// Fill up the first i positions with 0
fillWith0(scratch, i);
// Store second[i] * first in scratch, starting at position i.
// Make sure to 0-terminate scratch.
multiplyArrWithNumber(&scratch[i], intToChar(second[i]), first);
// Add pairwise elements with carry, stop at the end of scratch
addArrays(scratch, prod);
}
Our teacher gave us this exercise:
"Given a string like '-5,14' write a function that returns the float value of -5,14
I used double here just to test the precision, but it also didn't work with floats.
[also i'm from Europe, we use the comma instead of the dot. Oh also we aren't allowed to use the type string and bool, we have to "make" them like in C]
This is what i came up with, and it seems to work a little bit. Positive numbers are similar, but wrong, and given a negative number, the result is similar to 10 times the positive of the given number.
It should work like this:
I read the string into an array of characters;
I check if the first character is a minus. if so, subtract 1 from the number of integer figures because i will count them later starting from index 0;
I count the number of integer figures with a loop from the start of the array to the ',' character;
I count the number of decimal figures with a loop from after the ',' to the end of the string;
[Keep in mind for the next step that, following the ASCII table, the code for the character of a number is that number + 48]
I add to the result variable every integer figure multiplied by ten to the power of whatever place in the number it has.
I do the same for the deicmal values but with the negative exponent.
if the number was negative, i multiply the result with -1.
But for some reason it's not working properly. The lower the number is, the less accurate it is (given 4,5 the result is 9, but given 345,543 the result is 350,43)
#include <iostream>
#define EOS '\0'
#define DIM 100
#define TRUE 1
#define FALSE 0
void leggiN(char* c)
{
std::cout << "Insert a number: ";
std::cin >> c;
}
double stof(char* str)
{
double Result = 0;
double ascii_to_int = 48;
int i = 0;
int j = 0;
int IntegerDigits = 0;
int DecimalDigits = 0;
int CommaIndex;
int isNegative = FALSE;
if (str[0] == '-')
{
IntegerDigits = -1;
isNegative = TRUE;
}
while (str[i] != ',')
{
++IntegerDigits;
++i;
}
CommaIndex = i;
++i;
while (str[i] != EOS)
{
++DecimalDigits;
++i;
}
for (i = (CommaIndex - 1); i >= 0; --i)
{
Result += (str[i] - ascii_to_int) * (std::pow(10, j));
++j;
}
j = 0;
for (i = (CommaIndex + 1); str[i] != EOS; ++i)
{
Result += (str[i] - ascii_to_int) * (std::pow(10, -j));
++j;
}
if (isNegative == 1)
Result = Result * -1;
return Result;
}
int main()
{
char str[DIM];
leggiN(str);
std::cout << stof(str);
}
use j = 1 to start your second for loop. You are trying to raise 10 to the power of -0
j = 1;
for (i = (CommaIndex + 1); str[i] != EOS; ++i)
{
Result += (str[i] - ascii_to_int) * (std::pow(10, -j));
++j;
}
If your code return 9.0 when you enter "4,5", your problem has nothing to do with imprecision.
There are other problems in your code, I've tried to un it and got a SEGFAULT...
#include <iostream>
#define EOS '\0' // 0 being such a special value, there is no need to
// define a named constant for it.
#define DIM 100
#define TRUE 1 // the language defines boolean values, avoid defining
#define FALSE 0 // unnecessary named constants for something that already
// exists.
void leggiN(char* c)
{
std::cout << "Insert a number: ";
std::cin >> c; // Inserting from cin to a char* is a BIG no-no.
// some compilers won't even allow it, for good reasons
// i.e.: what is the length of the array pointed to?
}
double stof(char* str) // you are indicating that you may modify str?
{
double Result = 0;
double ascii_to_int = 48; // this is a terrible name.
int i = 0;
int j = 0;
int IntegerDigits = 0;
int DecimalDigits = 0;
int CommaIndex;
int isNegative = FALSE;
if (str[0] == '-') // is str a valid pointer? what happens if NULL ??
{
IntegerDigits = -1;
isNegative = TRUE;
// you fail to skip the sing character, should have ++i here.
}
while (str[i] != ',') // what happens if there is no ',' in the string?
{ // you should check for str[i] == 0.
++IntegerDigits;
++i;
}
CommaIndex = i;
++i;
while (str[i] != EOS)
{
++DecimalDigits; // why do you count decimal digits?
++i; // you do not use this result anyway...
}
for (i = (CommaIndex - 1); i >= 0; --i)
{
// what happens if you have non-digit characters? they participate
// in the conversion??
// you call std::pow(), but do not include <cmath> at the top of the file.
// isn't str[i] - '0' clearer ?
Result += (str[i] - ascii_to_int) * (std::pow(10, j));
++j;
}
j = 0;
for (i = (CommaIndex + 1); str[i] != EOS; ++i)
{
Result += (str[i] - ascii_to_int) * (std::pow(10, -j));
++j;
}
if (isNegative == 1) // you had defined constants fot this, but don't use them.
Result = Result * -1;
return Result;
}
int main()
{
char str[DIM];
leggiN(str);
std::cout << stof(str);
}
Here is one way to achieve what you want.
#include <iostream>
#include <string>
const char DECIMAL_POINT = ','; // we'll use a named constant here....
// usually, we'd have to check the locale
// for regional specific information.
// works like atod(), conversion stops at end of string of first illegal character.
double stof(const char* str) {
// check input, must be not null, not empty
if (!str || str[0] == 0)
return 0;
int i = 0;
bool isNegative = false;
// take care of leading sign
if (str[0] == '-' || str[0] == '+') {
isNegative = (str[0] == '-');
++i;
}
// convert integer part.
double result = 0;
while ('0' <= str[i] && str[i] <= '9') {
result = (result * 10) + (str[i] - '0');
++i;
}
// only do decimals if they are there.
if (str[i] != DECIMAL_POINT)
return (isNegative) ? -result : result;
++i; // skip decimal point
double decimals = 0;
double multiplier = .1;
while ('0' <= str[i] && str[i] <= '9') {
decimals += (str[i] - '0') * multiplier;
++i;
multiplier *= .1;
}
result += decimals;
return (isNegative) ? -result : result;
}
int main() {
// always use std::string to read strings from cin.
std::string str;
std::cout << "Insert a number: ";
std::cin >> str;
std::cout << "in: " << str << " out: " << stof(str.c_str()) << '\n';
return 0;
}
I'm doing a code that takes a text that is converted to binary, the program need to add every number converted, what I'm doing is to create an acumulator to add all the numbers to a single one, there are 200 binary nombers, the program goes well until the 18 iteration
The libraries:
#include <iostream>
#include <math.h>
#define MAX 200
#include <bitset>
#include <stdlib.h>
#include <sstream>
This is the main:
int main()
{
bitset<8>text[MAX];
string myString = "2074656d7075732e20446f6e65632076697461652073617069656e207574206c696265726f2076656e656e617469732066617563696275732e204e756c6c616d207175697320616e74652e20457469616d2073697420616d6574206f7263692065676574";
for (std::size_t i = 0; i < myString.size(); ++i){
text[i]=bitset<8>(myString.c_str()[i]);
}
int array[20];
int i=0;
long acumulator=0;
bool f=0;
for(int j=0;j<18;j++){
if(f==0){
string b = text[j].to_string();
long bn1 = atoi(b.c_str());
acumulator = add(bn1,0);
f=1;
}else{
string b = text[j].to_string();
long bn1 = atoi(b.c_str());
acumulator = add(bn1,acumulator);
}
}
cout<<acumulator;
return 0;
}
I convert the string into binary and save them into an array, then I call the "add" function, if its the first iteration, add the first number with a 0 and save the result in a var called "acumulator", then continue calling the function with the next number and the acumulator, all works till the 18 iteration, where start to adding weird numbers
The add function:
long add(long bn1,long bn2){
int r=0, i=0;
int sum[100];
stringstream ss;
while (bn1 != 0 || bn2 != 0) {
sum[i++] = (int)((bn1 % 10 + bn2 % 10 + r) % 2);
r = (int)((bn1 % 10 + bn2 % 10 + r) / 2);
bn1 = bn1 / 10;
bn2 = bn2 / 10;
}
if (r != 0){
sum[i++] = r;
}
for (int j = i-1; j >=0; j--){
ss << sum [j];
}
long result;
ss >> result;
return result;
}
Here I do the binary add and the result is transformed into a long, and return it to use it into the next iteration
And don't know why stop working in the 18 iteration, any idea of what is happening?
So my problem is bigger but I just do not know what to do with my code. I can do what I want if I use an array works just fine but we are not using arrays yet so I have no idea how to do it. So I have to take user input as a string validate that the string is 16 characters long, all of them are digits, and most importantly I have to multiply every other or even character by 2. Then if it is a double digit add the two digit (ex. 10 1+0). Oh by the way I do not know why but every time I do i%2 == 0 I get the odd numbers. Is it because i is unsigned?
for(unsigned i = 1; i < card.length(); i++){
if (i % 2 == 1){
}
else {
}
}
return sum;
}
You could use an array of strings where each string contains a number.
Go through them checking for 2 conditions:
Double the number if it is even (i.e., i % 2 == 0)
Add the digits if the number has 2 digits (i.e., string's length is 2)
Code:
#include <iostream>
#include <iterator> using namespace std;
int TOTAL_CARDS = 16;
void printCards(string msg, string *array) {
cout<<msg<<endl;
for(int i = 0; i < TOTAL_CARDS; i++) {
cout<<"array["<<i<<"]="<<array[i]<<endl;
}
cout<<"\n"<<endl; }
int main() {
string cards[TOTAL_CARDS];
// hardcoded numbers 0 up to TOTAL_CARDS for demo purposes
for(int i = 0; i < TOTAL_CARDS; i++) {
cards[i] = to_string(i);
}
printCards("Before:", cards);
for (unsigned i = 1; i < TOTAL_CARDS; i++){
// double if even
if (i % 2 == 0){
cards[i] = to_string(stoi(cards[i]) * 2);
}
// add digits if double digit number
if (cards[i].length() == 2) {
// get each digit
string currentNum = cards[i];
int firstDigit = currentNum[0] - '0'; // char - '0' gives int
int secondDigit = currentNum[1] - '0';
// do sum and put in array
int sum = firstDigit + secondDigit;
cards[i] = to_string(sum);
}
}
printCards("After:", cards); }
Output:
Before:
array[0]=0
array[1]=1
array[2]=2
array[3]=3
array[4]=4
array[5]=5
array[6]=6
array[7]=7
array[8]=8
array[9]=9
array[10]=10
array[11]=11
array[12]=12
array[13]=13
array[14]=14
array[15]=15
After:
array[0]=0
array[1]=1
array[2]=4
array[3]=3
array[4]=8
array[5]=5
array[6]=3
array[7]=7
array[8]=7
array[9]=9
array[10]=2
array[11]=2
array[12]=6
array[13]=4
array[14]=10
array[15]=6
If you wanted to get user input for the numbers:
// get user to enter numbers
cout<<"Please enter "<<TOTAL_CARDS<<" numbers: "<<endl;
for(int i = 0; i < TOTAL_CARDS; i++) {
cin>>cards[i];
}
I found the answer to it. I first needed to create char variable named num. Convert the char to an int using chnum and then multiply.
for(unsigned i = 0; i < card.length(); i++){
if (i % 2 == 1){
num = card.at(i);
chnum = (num -'0');
add = chnum * 2;
if(add >= 10){
char ho = (add + '0');
string str(1,ho);
for (unsigned j = 0; j < str.length();j++){
char digi = str.at(j);
int chub = (digi - '0');
cout << digi;
//add = (chub) + (chub);
}
}
sum += add;
}
I have a task that is difficult for me to handle. The task is: Create recursive function that can be generate a string of length N (N <= 100), formed by the letters 'A', 'B' and 'C' and does not containing two identical adjacent substring. For example: enter for N = 6 and the program should generate such a string in which no one else to repeated substrings: ABACAB. Wrong strings are: AABACA - because 'A' is to 'A'; ABCBCA - as 'BC' is to 'BC' and ABCABC is also wrong because 'ABC' is to 'ABC'.
I made a version of the program but an iterative way, here is the code:
#include <iostream>
#include <ctime>
using namespace std;
const char letters[] = "ABC";
char generate_rand()
{
return letters[rand() % 3];
}
int check(char *s, int pos)
{
for (int i = 1; i <= (pos + 1)/2; i++)
{
int flag = 1;
for (int j = 0; j < i; j++)
if (s[pos-j] != s[pos-i-j])
{
flag = 0;
break;
}
if (flag)
return 1;
}
return 0;
}
int main()
{
char s[100];
int n;
cout << "enter n: ";
cin >> n;
srand(time(NULL));
for (int i = 0; i < n; i++)
{
do
{
s[i] = generate_rand();
} while (check(s, i));
cout << s[i] << " ";
}
cout << " ok" << endl;
system("pause");
return 0;
}
I think the entrance of the recursive function may need to be the number of characters in the string, which will seek to repeat with an adjacent string and each time increased by 1, but not more than half the length of the original string, but do not know how to do it.
So lets start with a simple recursive function which prints 10 letters but doesn't check anything:
void addLetter(char* buf, int max_length)
{
int len = strlen(buf);
buf[len] = generate_rand();
if (strlen(buf) < max_length)
addLetter(buf);
}
int main()
{
srand(time(NULL)); //I forgot srand!
int max_length = 10; //ask user to input max_length, like you had earlier
char buf[100];
memset(buf,0,sizeof(buf));
addLetter(buf, max_length);
printf("\n%s\n", buf);
return 0;
}
Now lets change the recursive function, get it to check just 1 letter:
void addLetter(char* buf, int max_length)
{
int len = strlen(buf);
buf[len] = generate_rand();
if (len > 0)
{
if (buf[len] == buf[len-1])
buf[len] = 0;
}
if (strlen(buf) < max_length)
addLetter(buf);
}
Next step, check 2 letters with previous ones etc. You should be able to take it from here.