1

I'm coding this function where if a string differs only by one character, returns the distinct characters position, if they're right the same is supposed to return -1 and -10 in the case they differ by more than 1 character.

Just for giving and example, '010' and '110' or '100' and '110' works good, returning 0 and 1 each...

However, when I try with '100' and '101'or with '110' and '111' I get a result of -1 when it should be 2! I've done the desktop testing and I can't just see the mistake.

function combine (m1, m2 : string) : integer;
var
dash : integer;
distinct : integer;
i : integer;

begin
distinct := 0;
dash := -1;

for i := 0 to Length(m1)-1 do
begin
    if m1[i] <> m2[i] then
    begin
      distinct := distinct+1;
      dash := i;
      if distinct > 1 then
        begin
          result:= -10;
          exit;
        end;
    end;
end;
result := dash;
end;

I'm always getting same length strings, What am I doing wrong?

0

1 Answer 1

4

The main problem is that Delphi strings are 1-based. Your loop needs to run from 1 to Length(m1).

If you enabled range checking in the compiler options, then the compiler would have raised an error at runtime which would have led you to the fault. I cannot stress enough that you should enable range checking. It will lead to the compiler finding errors in your code.

Note also that this means that the returned values will also be 1-based. So an input of '100', '101' will give the result 3 since that is the index of the first difference.

You should also check that m1 and m2 are the same length. If not raise an exception.

Another tip. The idiomatic way to increment a variable by 1 is like so:

inc(distinct);

If you want to increment by a different value write:

inc(distinct, n);

So, I would write the function like this:

function combine(const m1, m2: string): integer;
var
  i: integer;
  dash: integer;
  distinct: integer;
begin
  if Length(m1)<>Length(m2) then begin
    raise EAssertionFailed.Create('m1 and m2 must be the same length');
  end;

  distinct := 0;
  dash := -1;

  for i := 1 to Length(m1) do
  begin
    if m1[i] <> m2[i] then
    begin
      inc(distinct);
      dash := i;
      if distinct > 1 then
      begin
        result := -10;
        exit;
      end;
    end;
  end;
  result := dash;
end;
Sign up to request clarification or add additional context in comments.

8 Comments

Pfff, THANKS so much. Many people will complain about my question but I'm just in a hurry coding in a language I never did. I just have one more question, What happened when I was accessing to the 0 index of the strings, why that didn't raise any sort of exception?
I agree with those people. Don't hurry. Take the time to learn your tools properly.
index 0 refers to the string meta data. That is the block containing the string's reference count, length, code page etc. Of course, that's implementation detail and accessing index 0 leads to undefined behaviour (I'm using the C/C++ interpretation of that term). You should enable range checking in the compiler options.
Did you see how my code was indented, by the way? Indenting your code properly in a question makes it much easier for us to answer. You can get the IDE to format your code for you before you post.
"The main problem is that Delphi strings are 1-based." Be careful with that, because that fact is slowly changing. Zero-based strings already exist starting with XE3 onwards. They are disabled by default in the Windows and Mac compilers, but are enabled by default in the mobile compilers. ZBSs can be enabled/disabled via a new {$ZEROBASEDSTRINGS ON|OFF} compiler directive.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.