Pset5 (Speller) Weird Valgrind memory errors, no leaks - valgrind

I have read other threads on pset5 Valgrind memory errors, but that didn't help me. I get 0 leaks, but this instead:
==1917== Conditional jump or move depends on uninitialised value(s)
Looks like you're trying to use a variable that might not have a value? Take a closer look at line 34 of dictionary.c.
The error refers to line 34 which is this: lower[i] = tolower(word[i]);
To supply context, the code below attempts to check if a word exists in the dictionary that has been uploaded to a hash table. I am attempting to convert the wanted word to lowercase because all the dictionary words are also lowercase and so that their hashes would be identical. The program successfully completes all tasks, but then stumbles upon these memory errors.
Any hints as to why Valgrind is mad at me? Thank you!
// Returns true if word is in dictionary else false
bool check(const char *word)
{
char lower[LENGTH + 1];
//Converts word to lower so the hashes of the dictionary entry and searched word would match
for (int i = 0; i < LENGTH + 1; i++)
{
lower[i] = tolower(word[i]);
}
// Creates node from the given bucket
node *tmp = table[hash(lower)];
// Traverses the linked list
while (tmp != NULL)
{
if (strcasecmp(word, tmp->word) == 0)
{
return true;
}
tmp = tmp->next;
}
return false;
}
Below is the whole dictionary.c file:
// Implements a dictionary's functionality
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table 26^3
const unsigned int N = 17576;
// Hash table
node *table[N];
int count = 0;
// Returns true if word is in dictionary else false
bool check(const char *word)
{
char lower[LENGTH + 1];
//Converts word to lower so the hashes of the dictionary entry and searched word would match
for (int i = 0; i < LENGTH + 1; i++)
{
lower[i] = tolower(word[i]);
}
// Creates node from the given bucket
node *tmp = table[hash(lower)];
// Traverses the linked list
while (tmp != NULL)
{
if (strcasecmp(word, tmp->word) == 0)
{
return true;
}
tmp = tmp->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// Modified hash function by Dan Berstein taken from http://www.cse.yorku.ca/~oz/hash.html
unsigned int hash = 5381;
int c;
while ((c = *word++))
{
hash = (((hash << 5) + hash) + c) % N; /* hash * 33 + c */
}
return hash;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
FILE *inptr = fopen(dictionary, "r");
if (dictionary == NULL)
{
printf("Could not load %s\n.", dictionary);
return false;
}
// Create a char array to temporarily hold the new word (r stands for read)
char r_word[N+1];
// Until the end of file
while (fscanf(inptr, "%s", r_word) != EOF)
{
// Increments count
count++;
// Create a node
node *new_node = malloc(sizeof(node));
if (new_node == NULL)
{
unload();
return false;
}
strcpy(new_node->word, r_word);
// Hash the node
int index = hash(new_node->word);
// Places the node at the right index
new_node->next = table[index];
table[index] = new_node;
}
fclose(inptr);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
if (&load == false)
{
return '0';
}
else
{
return count;
}
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
// Interates over the array
for (int i = 0; i < N; i++)
{
node *head = table[i];
while (head != NULL)
{
node *tmp = head;
head = head->next;
free(tmp);
}
}
return true;
}

This loop iterates through the maximum length of word-
for (int i = 0; i < LENGTH + 1; i++)
{
lower[i] = tolower(word[i]);
}
Except if you look at how word is created-
while (fscanf(inptr, "%s", r_word) != EOF)
{
// Increments count
count++;
// Create a node
node *new_node = malloc(sizeof(node));
if (new_node == NULL)
{
unload();
return false;
}
strcpy(new_node->word, r_word);
Notice, the variable r_word, may not be exactly of length LENGTH + 1. So what you really have in word is N number of characters, where N is not necessarily LENGTH + 1, it could be less.
So looping over the entire 0 -> LENGTH + 1 becomes problematic for words that are shorter than LENGTH + 1. You're going over array slots that do not have a value, they have garbage values.
What's the solution? This is precisely why c strings have \0-
for (int i = 0; word[i] != '\0'; i++)
{
lower[i] = tolower(word[i]);
}
This will stop the loop as soon as the NULL character is reached, which, you must have already learnt, marks the end of a string - aka a char array.
There may still be more errors in your code. But for your particular question - reading out of bounds is the answer.

Related

How to add JSpinner output into array and check for duplicate

I'm working on a code which has a JSpinner, which gives an output and moves it to int = n, I want to save every JSpinner output and add it into an array to check for duplicates and once found the JPanel should close itself or say you lost.
Scanner s = new Scanner(System.in);
int n = (Integer) spinner.getValue();
if (isPrime(n)) {
Input.setText(n + " is a prime number");
score++;
Highscore.setText("Score: " + score);
int[] array = new int[4];
for(int i=0; i<4;i++)
{
array[i]= (Integer) spinner.getValue();
}
for (int i=0; i < 4;i++)
{
System.out.println(array[i]);
}
Spinner output into array but it fills the whole array with one number example: [3,3,3,3].
private <T> boolean duplicate(T... array)
{
for (int i = 0; i < array.length; i++)
{
for (int j = i + 1; j < array.length; j++)
{
if (array[i] != null && array[i].equals(array[j])) {
return true;
dispose();
}
}
}
return false;
}
Duplicate check
I tried adding the user input from the JSpinner into an array and from there to check for duplicates.
Searched Online but could'nt find anything.
This if my first post so if you need anything more you can tell me.

How to check that two format strings are compatible?

Examples:
"Something %d" and "Something else %d" // Compatible
"Something %d" and "Something else %f" // Not Compatible
"Something %d" and "Something %d else %d" // Not Compatible
"Something %d and %f" and "Something %2$f and %1$d" // Compatible
I figured there should be some C function for this, but I'm not getting any relevant search results. I mean the compiler is checking that the format string and the arguments match, so the code for checking this is already written. The only question is how I can call it.
I'm using Objective-C, so if there is an Objective-C specific solution that's fine too.
Checking if 2 printf() format strings are compatible is an exercise in format parsing.
C, at least, has no standard run-time compare function such as:
int format_cmp(const char *f1, const char *f2); // Does not exist
Formats like "%d %f" and "%i %e" are obviously compatible in that both expect an int and float/double. Note: float are promoted to double as short and signed char are promoted to int.
Formats "%*.*f" and "%i %d %e" are compatible, but not obvious: both expect an int,int and float/double.
Formats "%hhd" and "%d" both expect an int, even though the first will have it values cast to signed char before printing.
Formats "%d" and "%u" are not compatible. Even though many systems will behaved as hoped. Note: Typically char will promote to int.
Formats "%d" and "%ld" are not strictly compatible. On a 32-bit system there are equivalent, but not in general. Of course code can be altered to accommodate this. OTOH "%lf" and "%f" are compatible due to the usual argument promotions of float to double.
Formats "%lu" and "%zu" may be compatible, but that depends on the implementation of unsigned long and size_t. Additions to code could allow this or related equivalences.
Some combinations of modifiers and specifiers are not defined like "%zp". The following does not dis-allow such esoteric combinations - but does compare them.
Modifiers like "$" are extensions to standard C and are not implemented in the following.
The compatibility test for printf() differs from scanf().
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
typedef enum {
type_none,
type_int,
type_unsigned,
type_float,
type_charpointer,
type_voidpointer,
type_intpointer,
type_unknown,
type_type_N = 0xFFFFFF
} type_type;
typedef struct {
const char *format;
int int_queue;
type_type type;
} format_T;
static void format_init(format_T *state, const char *format);
static type_type format_get(format_T *state);
static void format_next(format_T *state);
void format_init(format_T *state, const char *format) {
state->format = format;
state->int_queue = 0;
state->type = type_none;
format_next(state);
}
type_type format_get(format_T *state) {
if (state->int_queue > 0) {
return type_int;
}
return state->type;
}
const char *seek_flag(const char *format) {
while (strchr("-+ #0", *format) != NULL)
format++;
return format;
}
const char *seek_width(const char *format, int *int_queue) {
*int_queue = 0;
if (*format == '*') {
format++;
(*int_queue)++;
} else {
while (isdigit((unsigned char ) *format))
format++;
}
if (*format == '.') {
if (*format == '*') {
format++;
(*int_queue)++;
} else {
while (isdigit((unsigned char ) *format))
format++;
}
}
return format;
}
const char *seek_mod(const char *format, int *mod) {
*mod = 0;
if (format[0] == 'h' && format[1] == 'h') {
format += 2;
} else if (format[0] == 'l' && format[1] == 'l') {
*mod = ('l' << CHAR_BIT) + 'l';
format += 2;
} else if (strchr("ljztL", *format)) {
*mod = *format;
format++;
} else if (strchr("h", *format)) {
format++;
}
return format;
}
const char *seek_specifier(const char *format, int mod, type_type *type) {
if (strchr("di", *format)) {
*type = type_int;
format++;
} else if (strchr("ouxX", *format)) {
*type = type_unsigned;
format++;
} else if (strchr("fFeEgGaA", *format)) {
if (mod == 'l') mod = 0;
*type = type_float;
format++;
} else if (strchr("c", *format)) {
*type = type_int;
format++;
} else if (strchr("s", *format)) {
*type = type_charpointer;
format++;
} else if (strchr("p", *format)) {
*type = type_voidpointer;
format++;
} else if (strchr("n", *format)) {
*type = type_intpointer;
format++;
} else {
*type = type_unknown;
exit(1);
}
*type |= mod << CHAR_BIT; // Bring in modifier
return format;
}
void format_next(format_T *state) {
if (state->int_queue > 0) {
state->int_queue--;
return;
}
while (*state->format) {
if (state->format[0] == '%') {
state->format++;
if (state->format[0] == '%') {
state->format++;
continue;
}
state->format = seek_flag(state->format);
state->format = seek_width(state->format, &state->int_queue);
int mod;
state->format = seek_mod(state->format, &mod);
state->format = seek_specifier(state->format, mod, &state->type);
return;
} else {
state->format++;
}
}
state->type = type_none;
}
// 0 Compatible
// 1 Not Compatible
// 2 Not Comparable
int format_cmp(const char *f1, const char *f2) {
format_T state1;
format_init(&state1, f1);
format_T state2;
format_init(&state2, f2);
while (format_get(&state1) == format_get(&state2)) {
if (format_get(&state1) == type_none)
return 0;
if (format_get(&state1) == type_unknown)
return 2;
format_next(&state1);
format_next(&state2);
}
if (format_get(&state1) == type_unknown)
return 2;
if (format_get(&state2) == type_unknown)
return 2;
return 1;
}
Note: only minimal testing done. Lots of additional considerations could be added.
Known shortcomings: hh,h,l,ll,j,z,t modifiers with n. l with s,c.
[Edit]
OP comments about security concerns. This changes the nature of the post and the compare from an equality one to a security one. I'd imagine that one of the patterns (A) would be a reference pattern and the next (B) would be the test. The test would be "is B at least as secure as A?". Example A = "%.20s" and B1 = "%.19s", B2 = "%.20s", B3 = "%.21s". B1 and B2 both pass the security test as they do not extract more the 20 char. B3 is a problem as it goes pass the reference limit of 20 char. Further any non-width qualified with %s %[ %c is a security problem - in the reference or test pattern. This answer's code does not address this issue.
As mentioned, code does not yet handle modifiers with "%n".
[2018 edit]
Concerning "Formats "%d" and "%u" are not compatible.": This is for values to be printed in general. For values in the [0..INT_MAX] range, either format may work per C11dr ยง6.5.2.2 6.
My understanding of what you want, is that, you basically want a method which can look at two strings and detect if they both have the same types of values in them. Or something a long those lines.... If so, then try this (or something along the lines of this):
-(int)checkCompatible:(NSString *)string_1 :(NSString *)string_2 {
// Separate the string into single elements.
NSArray *stringArray_1 = [string_1 componentsSeparatedByString:#" "];
NSArray *stringArray_2 = [string_2 componentsSeparatedByString:#" "];
// Store only the numbers for comparison in a new array.
NSMutableArray *numbers_1 = [[NSMutableArray alloc] init];
NSMutableArray *numbers_2 = [[NSMutableArray alloc] init];
// Make sure the for loop below, runs for the appropriate
// number of cycles depending on which array is bigger.
int loopMax = 0;
if ([stringArray_1 count] > [stringArray_2 count]) {
loopMax = (int)[stringArray_1 count];
}
else {
loopMax = (int)[stringArray_2 count];
}
// Now go through the stringArray's and store only the
// numbers in the mutable array's. This will be used
// during the comparison stage.
for (int loop = 0; loop < loopMax; loop++) {
NSCharacterSet *notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if (loop < [stringArray_1 count]) {
if ([[stringArray_1 objectAtindex:loop] rangeOfCharacterFromSet:notDigits].location == NSNotFound) {
// String consists only of the digits 0 through 9.
[numbers_1 addObject:[stringArray_1 objectAtindex:loop]];
}
}
if (loop < [stringArray_2 count]) {
if ([[stringArray_2 objectAtindex:loop] rangeOfCharacterFromSet:notDigits].location == NSNotFound) {
// String consists only of the digits 0 through 9.
[numbers_2 addObject:[stringArray_2 objectAtindex:loop]];
}
}
}
// Now look through the mutable array's
// and perform the type comparison,.
if ([numbers_1 count] != [numbers_2 count]) {
// One of the two strings has more numbers
// than the other, so they are NOT compatible.
return 1;
}
else {
// Both string have the same number of numbers
// numbers so lets go through them to make
// sure the numbers are of the same type.
for (int loop = 0; loop < [numbers_1 count]; loop++) {
// Check to see if the number in the current array index
// is a float or an integer. All the numbers in the array have
// to be the SAME type, in order for the strings to be compatible.
BOOL check_float_1 = [[NSScanner scannerWithString:[numbers_1 objectAtindex:loop]] scanFloat:nil];
BOOL check_int_1 = [[NSScanner scannerWithString:[numbers_1 objectAtindex:loop]] scanInt:nil];
BOOL check_float_2 = [[NSScanner scannerWithString:[numbers_2 objectAtindex:loop]] scanFloat:nil];
BOOL check_int_2 = [[NSScanner scannerWithString:[numbers_2 objectAtindex:loop]] scanInt:nil];
if (check_float_1 == YES) {
if (check_float_2 == NO) {
return 1;
}
}
else if (check_int_1 == YES) {
if (check_int_2 == NO) {
return 1;
}
}
else {
// Error of some sort......
return 1;
}
}
// All the numbers in the strings are of the same
// type (otherwise we would NOT have reached
// this point). Therefore the strings are compatible.
return 0;
}
}

how to return longest words from an array?

given 2 arrays wrds[] , chars[] as an input to a function such that
wrds[] = [ "abc" , "baa" , "caan" , "an" , "banc" ]
chars[] = [ "a" , "a" , "n" , "c" , "b"]
Function should return the longest word from words[] which can be constructed from the chars in chars[] array.
for above example - "caan" , "banc" should be returned
Note: Once a character in chars[] array is used, it cant be used again.
eg: words[] = [ "aat" ]
characters[] = [ "a" , "t" ]
then word "aat" can't be constructed, since we've only 1 "a" in chars[].
There are kinds of anwers online but they are not written in Objective C.Can anyone help me solve this question in OC?
First, walk through the word array, one word at a time, throwing out all the words that can't be formed from the second array. To do that, for each word, walk through the characters of the word, throwing out that character from the second array. If we come to a character that's not in the second array, that word can't be formed from those characters.
Now we have an array consisting solely of the words that can be formed from those characters. Now sort that array by word length, longest first. Now start walking the array, looking at the length of each word. When that length value changes, stop; you have found all the longest words.
// Program do to do the same in C++
#include <iostream>
#include <string>
#include <map>
#include <vector>
using namespace std;
using std::vector;
vector<char*> match(char** words, int size, char* chars, map<char,int> &second)
{
vector<char*> res;
std::map<char,int> mapi = second;
int currsize = 0;
for(int i = 0; i < size ; i++){
char* wo;
wo = words[i];
int s= 0;
for( s=0; wo[s] != '\0'; s++){
}
if(s < currsize) {
//No need to iterate if already found a bigger word
//continue to see if the next word if bigger of the same size as currsize
continue;
}
// iterate through the map to see if all the letters present in the first array
bool found = true;
for(int j = 0; j <s ; j++){
map<char, int>::iterator it = mapi.find(wo[j]);
if(it == mapi.end()) {
found= false;
break;
}
}
if(!found) {
continue;
}
if(s > currsize) {
//remove the past res as found a bigger one
res.clear();
}
//Store this word in the vector as it is one of the biggest word so far
res.push_back(wo);
currsize = s;
}
return res;
}
int main()
{
map<char, int> leters;
char* words[5] = {"adc", "baa", "caan", "daanns", "banc"};
char ch1[]= {'a', 'a', 'n', 'c', 'b'};
int chsize = sizeof(ch1);
// put the ch1 chars in a map
for(int i = 0; i < chsize; i++) {
map<char,int>::iterator it =leters.find(ch1[i]);
if(it != leters.end()) {
it->second = it->second+1;
} else {
leters.insert(make_pair(ch1[i], 1));
}
}
char* chars = ch1;
vector<char*>v = match(words, 5, ch1, leters);
for(vector<char*>::iterator it = v.begin(); it != v.end(); it++) {
// it will print the result
cout << *it << endl;
}
return 0;
}

Arduino replace code

I'm very new to Arduino and C programming.
I'm making a GPS speedo and I'm trying to read in some serial, store a value from a substring and echo it back via serial.
At the moment I'm having problems storing the substring.
I've gotten to the point where I'm able to get some data between < and >.
But the data doesn't come in like that. It's a NMEA data stream and the data I want is between ,N, and ,K,.
So I've been trying to replace ,N, with < and ,K, with > .
Just can't get it to work. I get error: request for member 'replace' in 'c', which is of non-class type 'char'
Here's my code so far....
int indata = 0;
int scrubdata = 0;
char inString[32];
int stringPos = 0;
boolean startRead = false; // is reading?
void setup() {
Serial.begin(4800);
}
void loop() {
String pageValue = readPage();
Serial.print(pageValue);
}
String readPage(){
//read the page, and capture & return everything between '<' and '>'
stringPos = 0;
memset( &inString, 0, 32 ); //clear inString memory
while(true){
if (Serial.available() > 0) {
char c = Serial.read();
c.replace(",N,", "<");
c.replace(",K,", ">");
if (c == '<' ) { //'<' is our begining character
startRead = true; //Ready to start reading the part
}
else if(startRead){
if(c != '>'){ //'>' is our ending character
inString[stringPos] = c;
stringPos ++;
}
else{
//got what we need here! We can disconnect now
startRead = false;
return inString;
}
}
}
}
}
By Default:
Serial.read() returns an int if you must process the data this way, try casting it to char with:
char c = (char) Serial.read();
Another way to do this:
Would be to seek your beginning string (discarding un-needed data) using Serial.find() then reading data until you met your end character ",K," with Serial.readBytesUntil()
Something like this would work quite well:
char inData[64]; //adjust for your data size
Serial.setTimeout(2000); //Defaults to 1000 msecs set if necessary
Serial.find(",N,"); //Start of Data
int bRead = Serial.readBytesUntil(",K,", inData, 64); //Read until end of data
inData[bRead] = 0x00; //Zero terminate if using this as a string
return inData;

Use of blocks in Objective-C

const char *sentence = "He was not in the cab at the time.";
printf("\"%s\" has %d spaces\n", sentence, (int) ^ {
int i = 0;
int countSpaces = 0;
while (sentence[i] != '\0') {
if (sentence[i] == 0x20) {
countSpaces++;
}
i++;
}
return countSpaces;
});
This code simply counts the white space in a string, but for some reason it says 1606416608 spaces rather than 8. I'm not exactly sure what is going wrong, so thanks for any help!
You're passing the actual block to printf, not the result of the block. Instead, try
const char *sentence = "He was not in the cab at the time.";
printf("\"%s\" has %d spaces\n", sentence, (int) ^ {
int i = 0;
int countSpaces = 0;
while (sentence[i] != '\0') {
if (sentence[i] == 0x20) {
countSpaces++;
}
i++;
}
return countSpaces;
}()); // <-- note the extra parentheses here, indicating that you're calling the block