I made a function that will find any digits in an array and remove them. Here's my code:
int noNums (char *a) {
int i;
int deleteInd;
for (i = 0; (i < MAX_NAME_SZ) && (a[i] != '\0'); i++) {
if ((a[i] >= '0') && (a[i] <= '9')) {
deleteInd = i;
memmove (&a[deleteInd], &a[deleteInd + 1], strlen (a) - deleteInd);
}
}
}
If a number is by itself in the char array, then it is removed, no problem. However, if there are consecutive numbers in the array, then only every other digit will be deleted?
If my char array has
w12345678
then the array is changed to
w2468
instead of
w
Any ideas?
After you do the memmove(), the next element is now in the index of the element you just deleted. But your loop will do i++, so you won't check that index again. As a result, whenever there are two digits in a row, you skip the second one.
One way to fix this is to loop from the end of the array to the beginning, instead of from the beginning to the end.
Another way is to do i-- after doing the memmove(), to counteract the i++ that the loop will do.
if (isdigit(a[i]) {
deleteInd = i;
memmove (&a[deleteInd], &a[deleteInd + 1], strlen (a) - deleteInd);
i--;
}
BTW, you should use isdigit() to test whether a character is a digit.
Have you noticed that you are deleting the first digit then skipping one?
When iterating through the array, you start at position 0 and incrementing. When you delete a digit, you alter the string index.
i = 0 (char = w)
Index: 012345689
string: w12345678
i = 1 (char = 1)
Index: 012345689
string: w2345678
i = 2 (char = 3)
Index: 012345689
string: w2345678
Essentially, you are shifting the string over whenever you delete your character.
Don't increment i when you delete a character.
Note that deleteInd is not needed in your code, you could use i directly.
This is not an answer — Barmar's is — but both this and OP's other question shows they could use a fresh look into how to modify character arrays in place.
This is written in the hopes that this is useful to others learning C as well.
Elements, or sequences of elements, can be removed from an array efficiently, using a simple loop over its contents.
The key is to keep two indexes: one for the next element (or elements) to be examined, and one for the last element stored (or the next position to store to).
For example, to remove digits in an array, one can use the following pseudocode function:
Function removedigits(array, length):
Let i = 0 # Index of next element to examine, "input"
Let o = 0 # Position of next element to store, "output"
While (i < length):
If (array[i] is not a digit):
Let array[o] = array[i]
Let o = o + 1
End If
Let i = i + 1
End While
# For a string, we'll also want to terminate the array
# at o, because the rest of it contains garbage (old contents):
Let array[o] = '\0'
End Function
When dealing with sequences, it may be useful to keep multiple indexes. For example, to remove duplicate lines, one might use the following function:
Function removeduplicatelines(array):
Let i = 0 # Next position in the array to be examined
Let o = 0 # Next position in the array to store to
Let ostarted = 0 # Index at which the last line stored started at
# Loop over each input line:
While (array[i] != '\0'):
# Find the length of this line. It can end with a newline
# or at the end of the string. The newline is not included.
Let ilen = 0
While (array[i + ilen] != '\n' && array[i + ilen] != '\0'):
Let ilen = ilen + 1
End While
# If the already stored line is of different length
# (the +1 is for the newline, as it is not included in ilen)
# or if it does not match the input line, store input line.
If (ostarted + ilen + 1 != o || memcmp(array + ostarted, array + i, ilen) != 0):
# The lengths or content differs. Store the line.
# Copy ilen characters, starting at array[i],
# to array[o] onwards.
# Because the array parts do not overlap,
# we can safely use memcpy() here.
memcpy(array + o, array + i, ilen)
# It is now the last stored line.
Let ostarted = o
Let o = o + ilen
# If there is a newline following the line,
# store that too.
If (array[i + ilen] == '\n'):
Let array[o] = '\n'
Let o = o + 1
End If
Else:
# It is the same line again. Do not store.
End If
# Proceed to the next input line.
Let i = i + ilen
# Because the newline was not included in ilen,
# skip it if there is one.
If (array[i] == '\n'):
Let i = i + 1
End If
End While
# After index o, the array may contain old contents;
# so terminate the string at index o.
Let array[o] = '\0'
End Function
Note that memcmp() returns zero, if the ilen characters starting at array + ostarted match those starting at array + i.
This approach works, if we know o never exceeds i; that is, that we never overwrite array contents we haven't examined yet. But do note that o is allowed to be equal to i, as that just means we overwrite the same character we just examined, making no actual change in the array.
If we wanted to modify the function so that it skips empty lines, we add a new while loop before the existing one, to remove any leading newlines:
While (array[i] == '\n'):
Let i = i + 1
End While
and, to remove any empty lines, we modify the last part within the while loop into
# Because the newline was not included in ilen,
# skip it (and any additional newlines) if there is one.
While (array[i] == '\n'):
Let i = i + 1
End While
Finally, do note that the above removeduplicatelines() is very careful about not appending a newline after the last line, if there isn't one in the array to begin with.
I would like to find the size of the longest sequence of consecutive numbers in a random array of size 1xn using Matlab. I know that there are two ways to do this: 1) using a loop and 2) using Matlab functions e.g. find, but I am unsure about how to do this without using both?
E.G. [1 2 3 5 8 9 10 11 12 13 14 17]
The longest sequence in this would be 10 11 12 13 14, which would be of size 5.
I tried this but it doesn't work:
function [start, finish] = longest(sequence)
x = diff(t)==1;
f = find([false,x]~=[x,false]);
g = find(f(2:2:end)-f(1:2:end-1)>=N,1,'first');
Your variables don't match, but assuming that all(t == sequence) you are on the right track. You want to distinguish between the start of each run and the end by doing a second diff.
% Mark all sequences
x = diff(sequence) == 1;
% Take the second derivative to find the edges
xx = diff([false, x, false]);
% This gives matched pairs of indexes for each block
initial = find(xx == 1);
final = find(xx == -1);
% Get the block length
blockLength = final - initial;
% Get the max length
[~, idx] = max(blockLength);
% Return the indices
start = initial(idx);
finish = final(idx);
The result on your test gives start = 5, finish = 11. If you want to also return the block length, replace the ~ with your variable name
Pretty simple problem, I want to create an array with char in a for loop.
code:
a = [1:5];
arr = [];
for i = 1:length(a)
arr(i) = ['f_',num2str(i)]
end
I am getting error:
In an assignment A(I) = B, the number of elements in B and I must be the same.
all i want is an array:
[f_1 f_2 f_3....]
This is because arr(i) is a single element, while ['f:', num2str(i)] contain three characters. Also, for i = 1:length(1) doesn't really make sense, since length(1) is guaranteed to be 1. I guess you wanted for i = 1:length(a). If that's the case I suggest you substitute length with numel and i with ii.
The better way to create the array you want is using sprintf like this:
sprintf('f_%i\n',1:5)
ans =
f_1
f_2
f_3
f_4
f_5
Or possiblby:
sprintf('f_%i ',1:5)
ans =
f_1 f_2 f_3 f_4 f_5
I guess this is what you really wanted:
for ii = 1:5
arr{ii} = ['f_', num2str(ii)];
end
arr =
'f_1' 'f_2' 'f_3' 'f_4' 'f_5'
Or simpler:
arr = arrayfun(#(n) sprintf('f_%i', n), 1:5, 'UniformOutput', false)
The last two can be indexed as follows:
arr{1}
ans =
f_1
You can also do (same result):
str = sprintf('f_%i\n', 1:5);
arr = strsplit(str(1:end-1), '\n')
If you're doing this to create variable names, then please don't. Use cells or structs instead.
I want to create a game, which monster is aligned from left to right horizontally, the order of monsters has other logical meaning (e.g.: the appearing sequence), but I want to play some effects which starts from the middle monster
the array, for example, for odd number size array:
int[] a=new int[]{1,2,3,4,5};
the access sequence is 3,2,4,1,5 (or 3,4,2,5,1)
for even number size array:
int[] a=new int[]{1,2,3,4,5,6};
the access sequence is 3,4,2,5,1,6 or (4,3,5,2,6,1)
If it is in something like vector in c++, it will be:
std::vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
a.push_back(5);
while(a.size()>0){
printf("%d\n",a[a.size()/2]);
a.erase(a.begin()+a.size()/2);
}
which the output is
3
4
2
5
1
But I want an algorithm which is suitable to be used in array, which the position of element cannot be changed,
I tried something like:
int a[]={1,2,3,4,5};
for(int i=a.size()/2;i>=0 && i<a.size();i=XXXX){
printf("%d\n",a[i]);
}
which XXXX is the update statement, which I still don't know what should it be.
In fact, I don't know if my init value and condition statement in for loop is correct. I even don't know if it can be done by a single loop.
Ok, I know I can have a temp vector and then copy the index to do that, but I also want to know if it can be done in a single for loop without any temp vector or array.
Can anyone help (or is there another simple algorithm to do that?)?
This is an answer for the edited question that is language-agnostic and wants a single function to display the elements in the stated order.
First, chose a "middle" index.
var i = Math.floor((a.length-1)/2);
Then alternate right and left moving outwards incrementally until either edge of the array is encountered.
To facilitate this, start with a variable d = 0 which will be the distance from the middle element. This d will be updated like so upon each iteration
d += -(2*d) + (d > 0 ? 0 : 1);
with the below update pattern:
0, 1, -1, 2, -2, ...
If the middle index is 2 in array [1,2,3,4,5], then applying a[i + d] will result in
3, 4, 2, 5, 1
I hope this is what you are looking for.
Here is a JavaScript implementation:
var a = [1,2,3,4,5,7,8];
var i = Math.floor((a.length-1)/2);
for (var d = 0; i+d >= 0 && i+d < a.length;) {
// Print out the value
console.log(a[i + d]);
// Outward-moving logic
d += -(2*d) + (d > 0 ? 0 : 1);
}
or if you want this all in the for-loop like you've tried in your question, you can do this:
var a = [1,2,3,4,5,7,8];
var i = Math.floor((a.length-1)/2);
for (var d = 0; i+d >= 0 && i+d < a.length; d += -(2*d) + (d > 0 ? 0 : 1)) {
console.log( a[i + d] ); // print the value
}
Result on [1,2,3,4,5] (odd-length array):
3 4 2 5 1
Result on [1,2,3,4,5,6,7,8] (even-length array):
4 5 3 6 2 7 1 8
Demo: JSBin
An algorithm to list the elements from innermost to outermost is to pull off the last and first entries (pop and shift) in the array in alternation until no elements are left, then reverse the list of what you have pulled off. This works for odd and even-length arrays naturally.
For example,
1,2,3,4,5,6
1,2,3,4,5 6
2,3,4,5 6,1
2,3,4 6,1,5
3,4 6,1,5,2
3 6,1,5,2,4
6,1,5,2,4,3
3,4,2,5,1,6 // Reversed list from above
and
1,2,3,4,5
1,2,3,4 5
2,3,4 5,1
2,3 5,1,4
3 5,1,4,2
5,1,4,2,3
3,2,4,1,5 // Reversed list from above
You can use this above algorithm to create an index map array which you can use to access your main array in the order you requested. For example:
// Start with an array of indices
// from 0..arr.length-1
0,1,2,3,4
0,1,2,3 4
1,2,3 4,0
1,2 4,0,3
2 4,0,3,1
4,0,3,1,2
2,1,3,0,4 // Reversed list from above
Then you have a mapping array
int[] arr = new int[]{1,2,3,4,5};
int[] map = new int[]{2,1,3,0,4};
which you can use to access your main array, for example
arr[map[0]]; // returns 3
Edit: Added Java implementation and demo.
public static int[] creatIndexMap(int length) {
// Create a deque so elements can be removed from both ends
Deque<Integer> tmp = new LinkedList<Integer>();
for(int i = 0; i < length; i++) {
tmp.add(i);
}
// In alternation remove the last and first entries of tmp
// and add them in reverse order to the map array
int[] map = new int[length];
int index = length-1;
while (!tmp.isEmpty()) {
// Remove last element
map[index--] = (int) tmp.removeLast();
// Remove first element
if(!tmp.isEmpty()) {
map[index--] = (int) tmp.removeFirst();
}
}
return map;
}
Demo: IDEOne